<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
	
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<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>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></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>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
1595 Emory Road
[>img[Bob Brown|http://www.emorycottage.net/images/bbrown_2005_200.jpg]]
I am the owner of the property at 1595 Emory Road.  I bought it over 30 years ago.  A fiasco with re-roofing made the house uninhabitable and quickly destroyed the structural integrity of the roof, making repairs impossible.  I suppose I should have sued the roofing company, but I did not.

The recent sale of some property I inherited, also about 30 years ago, in another state, has made it possible for me to rebuild the house at 1595 Emory Road, and I am keeping the exterior appearance as close to the original house as the Historic Preservation Commission will allow.  (I find it ironic that the barrier to historic accuracy is the Historic Preservation Commission.)
//2008-06-01//
* Extensive revisions to match decisions made previously and to match V-3 drawings.

//2008-05-29//
* Edited the [[Kitchen]] section to be sure we don't forget about pot racks.  Also added some descriptive text about the center island.

//2008-04-13//
* Edited the "Roof" section of [[Exterior]] to reflect that I've seen a Maxi Tile sample.

//2008-04-07//
* Included the front elevation drawing on the [[Program]] Page.

//2008-03-27//
* Added some notes on whole-house ventilation under [[HVAC]]
* Corrected error in [[Lighting and Electrical]] to show that the wireless network drop is in the hall closet, not the attic.  Made it clearer that the owner-supplied network equipment is to be installed by the owner after the house is occupied.
* Added notes about stenciled concrete to [[Exterior]].

//2008-03-23//
* Added the items from the appliance schedule plus owner-supplied items to [[Kitchen]]

//2008-03-22//
* Revised the section on flooring in the [[general program|Program]]; dining room to be hardwood.  (Still want travertine in the gallery if we can make it happen.)
* Added a note on exterior appearance in [[Exterior]] and added information on the front entrance and railings.
* Added a "Landscaping" section in [[Exterior]] and moved some landscaping notes from the general program.
* Moved "Roof" to be a sub-category of [[Exterior]] and added note that faux tile products require a minimum 3 to 12 pitch.  Also added a note about samples being sent to Billy Livingston.
* Battens for pot racks added to [[kitchen|Kitchen]] notes.
* Revised whole-house ventilation description to place fan in garage as discussed on March 21.
* Added notes on low-voltage wiring (doorbell, telephone, network) to [[Lighting and Electrical]].
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #FF8614
PrimaryMid: #DA4A0D
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
{{{
// This is the BlueLinkWebs account for Emory Cottage
_uacct = "UA-528304-3";

  // Overide displayTiddler function to also Google Analytics urchin.
  var CustomTracker = {}; // Create a namespace for our new function.
  CustomTracker.displayTiddler = story.displayTiddler;
  story.displayTiddler = function(srcElement,titles,template,unused1,unused2,animate,unused3)
  {
    if ((urchinTracker) && (readOnly)) {
    if ( typeof CustomTracker.counter == 'undefined' ) {  // It has not been defined... perform the initilization
        CustomTracker.counter = 0;
    }
      var trackTitle = titles;
      if (typeof trackTitle == 'object') trackTitle='';
      if (CustomTracker.counter > 0)  {
        urchinTracker('/' + trackTitle);
        // alert("Tracking: "+trackTitle);
      }
      CustomTracker.counter++;
    }
    CustomTracker.displayTiddler.apply(this,arguments);
  }

}}}
[[News]]
[[What's in a Name?]]
[[Program]]
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.8.4|
|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|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ("~PureStore" format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Inline control panel (live):
><<exportTiddlers inline>>
!!!!!Revisions
<<<
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
|please see [[ExportTiddlersPluginInfo]] for additional revision details|
2005.10.09 [0.0.0] development started
<<<
!!!!!Code
***/
//{{{
// version
version.extensions.ExportTiddlersPlugin= {major: 2, minor: 8, revision: 4, date: new Date(2008,9,29)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers="<<exportTiddlers inline>>";

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:"export",
		tooltip:"Export selected tiddlers to another file",
		content:"<<exportTiddlers inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask")+1,0,"exportTask");
}

// $(...) function: 'shorthand' convenience syntax for document.getElementById()
if (typeof($)=="undefined") { // avoid redefinition
function $() {
	var elements=new Array();
	for (var i=0; i<arguments.length; i++) {
		var element=arguments[i];
		if (typeof element=='string') element=document.getElementById(element);
		if (arguments.length==1) return element;
		elements.push(element);
	}
	return elements;
}
}

config.macros.exportTiddlers = {
	label: "export tiddlers",
	prompt: "Copy selected tiddlers to an export document",
	okmsg: "%0 tiddlers written to %1",
	failmsg: "An error occurred while creating %1",
	mergeprompt: "%0\nalready contains tiddler definitions.\n"
		+"\nPress OK to add new/revised tiddlers to current file contents."
		+"\nPress Cancel to completely replace file contents",
	mergestatus: "Merged %0 new/revised tiddlers with %1 previously saved tiddlers",
	statusmsg: "%0 tiddler%1 - %2 selected for export",
	newdefault: "export.html",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss",  // for "filter date/time" edit fields
	type_TW: "tw", type_PS: "ps", type_TX: "tx", type_NF: "nf", // file type tokens
	type_map: { // map filetype param alternatives/abbreviations to token values
		tiddlywiki:"tw", tw:"tw", wiki: "tw",
		purestore: "ps", ps:"ps", store:"ps",
		plaintext: "tx", tx:"tx", text: "tx",
		newsfeed:  "nf", nf:"nf", xml:  "nf", rss:"nf"
	},
	handler: function(place,macroName,params) {
		if (params[0]!="inline")
			{ createTiddlyButton(place,this.label,this.prompt,this.togglePanel); return; }
		var panel=this.createPanel(place);
		panel.style.position="static";
		panel.style.display="block";
	},
	createPanel: function(place) {
		var panel=$("exportPanel");
		if (panel) { panel.parentNode.removeChild(panel); }
		setStylesheet(this.css,"exportTiddlers");
		panel=createTiddlyElement(place,"span","exportPanel",null,null)
		panel.innerHTML=this.html;
		this.initFilter();
		this.refreshList(0);
		var fn=$("exportFilename");
		if (window.location.protocol=="file:" && !fn.value.length) {
			// get new target path/filename
			var newPath=getLocalPath(window.location.href);
			var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
			if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
			fn.value=newPath+this.newdefault;
		}
		return panel;
	},
	togglePanel: function(e) {
		if (!e) var e = window.event;
		var parent=resolveTarget(e).parentNode;
		var panel = $("exportPanel");
		if (panel==undefined || panel.parentNode!=parent)
			panel=config.macros.exportTiddlers.createPanel(parent);
		var isOpen = panel.style.display=="block";
		if(config.options.chkAnimate)
			anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
		else
			panel.style.display = isOpen ? "none" : "block" ;
		if (panel.style.display!="none") { // update list and set focus when panel is made visible
			config.macros.exportTiddlers.refreshList(0);
			var fn=$("exportFilename"); fn.focus(); fn.select();
		}
		e.cancelBubble = true;
		if (e.stopPropagation) e.stopPropagation();
		return(false);
	},
	css: '\
		#exportPanel {\
			display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\
			background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
			border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
			padding: 0.5em; margin:0em; -moz-border-radius:1em;\
		}\
		#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
		#exportPanel table { \
			width:100%; border:0px; padding:0px; margin:0px;\
			font-size:8pt; line-height:110%; background:transparent;\
		}\
		#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
		#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\
		#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%; }\
		#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:8pt; }\
		#exportPanel .box { \
			border:1px solid black; padding:3px; margin-bottom:5px; \
			background:#f8f8f8; -moz-border-radius:5px; }\
		#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
		#exportPanel .rad { width:auto;border:0 }\
		#exportPanel .chk { width:auto;border:0 }\
		#exportPanel .btn { width:auto; }\
		#exportPanel .btn1 { width:98%; }\
		#exportPanel .btn2 { width:48%; }\
		#exportPanel .btn3 { width:32%; }\
		#exportPanel .btn4 { width:24%; }\
		#exportPanel .btn5 { width:19%; }\
	',
	html: '\
		<!-- target path/file  -->\
		<div>\
		export to path/filename:<br>\
		<input type="text" id="exportFilename" size=40 style="width:93%"><input \
			type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
			onclick="var fn=config.macros.exportTiddlers.askForFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
		</div>\
		<!-- output format -->\
		<div>\
		output file format:\
		<select id="exportFormat" size=1>\
			<option value="TW">TiddlyWiki HTML document (includes core code)</option>\
			<option value="PS">TiddlyWiki "PureStore" HTML file (tiddler data only)</option>\
			<option value="TX">TiddlyWiki plain text TXT file (tiddler source listing)</option>\
			<option value="NF">RSS NewsFeed XML file</option>\
		</select>\
		</div>\
		<!-- notes -->\
		<div>\
		notes:<br>\
		<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
		</div>\
		<!-- list of tiddlers -->\
		<table><tr align="left"><td>\
			select:\
			<a href="JavaScript:;" id="exportSelectAll"\
				onclick="config.macros.exportTiddlers.process(this)" title="select all tiddlers">\
				&nbsp;all&nbsp;</a>\
			<a href="JavaScript:;" id="exportSelectChanges"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers changed since last save">\
				&nbsp;changes&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectOpened"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers currently being displayed">\
				&nbsp;opened&nbsp;</a> \
			<a href="JavaScript:;" id="exportSelectRelated"\
				onclick="config.macros.exportTiddlers.process(this)" title="select tiddlers related to the currently selected tiddlers">\
				&nbsp;related&nbsp;</a> \
			<a href="JavaScript:;" id="exportToggleFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="show/hide selection filter">\
				&nbsp;filter&nbsp;</a>  \
		</td><td align="right">\
			<a href="JavaScript:;" id="exportListSmaller"\
				onclick="config.macros.exportTiddlers.process(this)" title="reduce list size">\
				&nbsp;&#150;&nbsp;</a>\
			<a href="JavaScript:;" id="exportListLarger"\
				onclick="config.macros.exportTiddlers.process(this)" title="increase list size">\
				&nbsp;+&nbsp;</a>\
		</td></tr></table>\
		<select id="exportList" multiple size="10" style="margin-bottom:5px;"\
			onchange="config.macros.exportTiddlers.refreshList(this.selectedIndex)">\
		</select><br>\
		</div><!--box-->\
		<!-- selection filter -->\
		<div id="exportFilterPanel" style="display:none">\
		<table><tr align="left"><td>\
			selection filter\
		</td><td align="right">\
			<a href="JavaScript:;" id="exportHideFilter"\
				onclick="config.macros.exportTiddlers.process(this)" title="hide selection filter">hide</a>\
		</td></tr></table>\
		<div class="box">\
		<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> starting date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterStartBy" \
				onchange="config.macros.exportTiddlers.showFilterFields(this);">\
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
			</select>\
		</td><td width="50%">\
			<input type="text" id="exportStartDate" onfocus="this.select()"\
				onchange="$(\'exportFilterStartBy\').value=\'other\';">\
		</td></tr></table>\
		<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> ending date/time<br>\
		<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
			<select size=1 id="exportFilterEndBy" \
				onchange="config.macros.exportTiddlers.showFilterFields(this);">\
				<option value="0">today</option>\
				<option value="1">yesterday</option>\
				<option value="7">a week ago</option>\
				<option value="30">a month ago</option>\
				<option value="file">file date</option>\
				<option value="other">other (mm/dd/yyyy hh:mm)</option>\
			</select>\
		</td><td width="50%">\
			<input type="text" id="exportEndDate" onfocus="this.select()"\
				onchange="$(\'exportFilterEndBy\').value=\'other\';">\
		</td></tr></table>\
		<input type="checkbox" class="chk" id=exportFilterTags value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match tags<br>\
		<input type="text" id="exportTags" onfocus="this.select()">\
		<input type="checkbox" class="chk" id=exportFilterText value="1"\
			onclick="config.macros.exportTiddlers.showFilterFields(this)"> match titles/tiddler text<br>\
		<input type="text" id="exportText" onfocus="this.select()">\
		</div> <!--box-->\
		</div> <!--panel-->\
		<!-- action buttons -->\
		<div style="text-align:center">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportFilter" value="apply filter">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportStart" value="export tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportDelete" value="delete tiddlers">\
		<input type=button class="btn4" onclick="config.macros.exportTiddlers.process(this)"\
			id="exportClose" value="close">\
		</div><!--center-->\
	',
	process: function(which) { // process panel control interactions
		// DEBUG alert(which.id);
		var theList=$('exportList'); if (!theList) return;
		var count = 0;
		var total = store.getTiddlers('title').length;
		switch (which.id) {
			case 'exportFilter':
				count=this.filterExportList();
				var panel=$('exportFilterPanel');
				if (count==-1) { panel.style.display='block'; break; }
				$("exportStart").disabled=(count==0);
				$("exportDelete").disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
				break;
			case 'exportStart':
				this.go();
				break;
			case 'exportDelete':
				this.deleteTiddlers();
				break;
			case 'exportHideFilter':
			case 'exportToggleFilter':
				var panel=$('exportFilterPanel')
				panel.style.display=(panel.style.display=='block')?'none':'block';
				break;
			case 'exportSelectChanges':
				var lastmod=new Date(document.lastModified);
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=="") continue;
					var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
					theList.options[t].selected=(tiddler.modified>lastmod);
					count += (tiddler.modified>lastmod)?1:0;
				}
				$("exportStart").disabled=(count==0);
				$("exportDelete").disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert("There are no unsaved changes");
				break;
			case 'exportSelectAll':
				for (var t = 0; t < theList.options.length; t++) {
					if (theList.options[t].value=="") continue;
					theList.options[t].selected=true;
					count += 1;
				}
				$("exportStart").disabled=(count==0);
				$("exportDelete").disabled=(count==0);
				this.displayStatus(count,count);
				break;
			case 'exportSelectOpened':
				for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
				var tiddlerDisplay = $("tiddlerDisplay"); // for TW2.1-
				if (!tiddlerDisplay) tiddlerDisplay = $("storyDisplay"); // for TW2.2+
				for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
					var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
					for (var i = 0; i < theList.options.length; i++) {
						if (theList.options[i].value!=tiddler) continue;
						theList.options[i].selected=true; count++; break;
					}
				}
				$("exportStart").disabled=(count==0);
				$("exportDelete").disabled=(count==0);
				this.displayStatus(count,total);
				if (count==0) alert("There are no tiddlers currently opened");
				break;
			case 'exportSelectRelated':
				// recursively build list of related tiddlers
				function getRelatedTiddlers(tid,tids) {
					var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
					tids.push(t.title);
					if (!t.linksUpdated) t.changed();
					for (var i=0; i<t.links.length; i++)
						if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
					return tids;
				}
				// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
				var tids=[];
				for (var i=0; i<theList.options.length; i++)
					if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
				// select related tiddlers (includes original selected tiddlers)
				for (var i=0; i<theList.options.length; i++)
					theList.options[i].selected=tids.contains(theList.options[i].value);
				this.displayStatus(tids.length,total);
				break;
			case 'exportListSmaller':	// decrease current listbox size
				var min=5;
				theList.size-=(theList.size>min)?1:0;
				break;
			case 'exportListLarger':	// increase current listbox size
				var max=(theList.options.length>25)?theList.options.length:25;
				theList.size+=(theList.size<max)?1:0;
				break;
			case 'exportClose':
				$('exportPanel').style.display='none';
				break;
		}
	},
	displayStatus: function(count,total) {
		var txt=this.statusmsg.format([total,total!=1?'s':'',!count?"none":count==total?"all":count]);
		clearMessage();	displayMessage(txt);
		return txt;
	},
	refreshList: function(selectedIndex) {
		var theList = $("exportList"); if (!theList) return;
		// get the sort order
		var sort;
		if (!selectedIndex)   selectedIndex=0;
		if (selectedIndex==0) sort='modified';
		if (selectedIndex==1) sort='title';
		if (selectedIndex==2) sort='modified';
		if (selectedIndex==3) sort='modifier';
		if (selectedIndex==4) sort='tags';

		// unselect headings and count number of tiddlers actually selected
		var count=0;
		for (var t=5; t < theList.options.length; t++) {
			if (!theList.options[t].selected) continue;
			if (theList.options[t].value!="")
				count++;
			else { // if heading is selected, deselect it, and then select and count all in section
				theList.options[t].selected=false;
				for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
					theList.options[t].selected=true;
					count++;
				}
			}
		}

		// disable "export" and "delete" buttons if no tiddlers selected
		$("exportStart").disabled=(count==0);
		$("exportDelete").disabled=(count==0);

		// show selection count
		var tiddlers = store.getTiddlers('title');
		if (theList.options.length) this.displayStatus(count,tiddlers.length);

		// if a [command] item, reload list... otherwise, no further refresh needed
		if (selectedIndex>4) return;

		// clear current list contents
		while (theList.length > 0) { theList.options[0] = null; }
		// add heading and control items to list
		var i=0;
		var indent=String.fromCharCode(160)+String.fromCharCode(160);
		theList.options[i++]=
			new Option(tiddlers.length+" tiddlers in document", "",false,false);
		theList.options[i++]=
			new Option(((sort=="title"   )?">":indent)+' [by title]', "",false,false);
		theList.options[i++]=
			new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
		theList.options[i++]=
			new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
		theList.options[i++]=
			new Option(((sort=="tags"    )?">":indent)+' [by tags]', "",false,false);

		// output the tiddler list
		switch(sort) {
			case "title":
				for(var t = 0; t < tiddlers.length; t++)
					theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
				break;
			case "modifier":
			case "modified":
				var tiddlers = store.getTiddlers(sort);
				// sort descending for newest date first
				tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
				var lastSection = "";
				for(var t = 0; t < tiddlers.length; t++) {
					var tiddler = tiddlers[t];
					var theSection = "";
					if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
					if (sort=="modifier") theSection=tiddler.modifier;
					if (theSection != lastSection) {
						theList.options[i++] = new Option(theSection,"",false,false);
						lastSection = theSection;
					}
					theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
				break;
			case "tags":
				var theTitles = {}; // all tiddler titles, hash indexed by tag value
				var theTags = new Array();
				for(var t=0; t<tiddlers.length; t++) {
					var title=tiddlers[t].title;
					var tags=tiddlers[t].tags;
					if (!tags || !tags.length) {
						if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
						theTitles["untagged"].push(title);
					}
					else for(var s=0; s<tags.length; s++) {
						if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
						theTitles[tags[s]].push(title);
					}
				}
				theTags.sort();
				for(var tagindex=0; tagindex<theTags.length; tagindex++) {
					var theTag=theTags[tagindex];
					theList.options[i++]=new Option(theTag,"",false,false);
					for(var t=0; t<theTitles[theTag].length; t++)
						theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
				}
				break;
			}
		theList.selectedIndex=selectedIndex; // select current control item
		$("exportStart").disabled=true;
		$("exportDelete").disabled=true;
		this.displayStatus(0,tiddlers.length);
	},
	askForFilename: function(here) {
		var msg=here.title; // use tooltip as dialog box message
		var path=getLocalPath(document.location.href);
		var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
		if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
		var filetype=$("exportFormat").value.toLowerCase();
		var defext='html';
		if (filetype==this.type_TX) defext='txt';
		if (filetype==this.type_NF) defext='xml';
		var file=this.newdefault.replace(/html$/,defext);
		var result="";
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension=defext;
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XPSP2 IE only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|XML files|*.xml|';
				s.FilterIndex=defext=="txt"?2:"html"?3:"xml"?4:1;
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) {  // fallback
				var result=prompt(msg,path+file);
			}
		}
		return result;
	},
	initFilter: function() {
		// start date
		$("exportFilterStart").checked=false;
		$("exportStartDate").value="";
		// end date
		$("exportFilterEnd").checked=false;
		$("exportEndDate").value="";
		// tags
		$("exportFilterTags").checked=false;
		$("exportTags").value="";
		// text
		$("exportFilterText").checked=false;
		$("exportText").value="";
		// show/hide filter input fields
		this.showFilterFields();
	},
	showFilterFields: function(which) {
		var show=$('exportFilterStart').checked;
		$('exportFilterStartBy').style.display=show?"block":"none";
		$('exportStartDate').style.display=show?"block":"none";
		var val=$('exportFilterStartBy').value;
		$('exportStartDate').value
			=this.getFilterDate(val,'exportStartDate').formatString(this.datetimefmt);
		if (which && (which.id=='exportFilterStartBy') && (val=='other'))
			$('exportStartDate').focus();

		var show=$('exportFilterEnd').checked;
		$('exportFilterEndBy').style.display=show?"block":"none";
		$('exportEndDate').style.display=show?"block":"none";
		var val=$('exportFilterEndBy').value;
		$('exportEndDate').value
			=this.getFilterDate(val,'exportEndDate').formatString(this.datetimefmt);
		 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
			$('exportEndDate').focus();

		var show=$('exportFilterTags').checked;
		$('exportTags').style.display=show?"block":"none";

		var show=$('exportFilterText').checked;
		$('exportText').style.display=show?"block":"none";
	},
	getFilterDate: function(val,id) {
		var result=0;
		switch (val) {
			case 'file':
				result=new Date(document.lastModified);
				break;
			case 'other':
				result=new Date($(id).value);
				break;
			default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
				var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
				var oneday=86400000;
				if (id=='exportStartDate')
					result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
				else
					result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
				break;
		}
		return result;
	},
	filterExportList: function() {
		var theList  = $("exportList"); if (!theList) return -1;
		var filterStart=$("exportFilterStart").checked;
		var val=$("exportFilterStartBy").value;
		var startDate=config.macros.exportTiddlers.getFilterDate(val,'exportStartDate');
		var filterEnd=$("exportFilterEnd").checked;
		var val=$("exportFilterEndBy").value;
		var endDate=config.macros.exportTiddlers.getFilterDate(val,'exportEndDate');
		var filterTags=$("exportFilterTags").checked;
		var tags=$("exportTags").value;
		var filterText=$("exportFilterText").checked;
		var text=$("exportText").value;
		if (!(filterStart||filterEnd||filterTags||filterText)) {
			alert("Please set the selection filter");
			$('exportFilterPanel').style.display="block";
			return -1;
		}
		if (filterStart&&filterEnd&&(startDate>endDate)) {
			var msg="starting date/time:\n"
			msg+=startDate.toLocaleString()+"\n";
			msg+="is later than ending date/time:\n"
			msg+=endDate.toLocaleString()
			alert(msg);
			return -1;
		}
		// if filter by tags, get list of matching tiddlers
		// use getMatchingTiddlers() (if MatchTagsPlugin is installed) for full boolean expressions
		// otherwise use getTaggedTiddlers() for simple tag matching
		if (filterTags) {
			var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
			var t=fn.apply(store,[tags]);
			var tagged=[];
			for (var i=0; i<t.length; i++) tagged.push(t[i].title);
		}
		// scan list and select tiddlers that match all applicable criteria
		var total=0;
		var count=0;
		for (var i=0; i<theList.options.length; i++) {
			// get item, skip non-tiddler list items (section headings)
			var opt=theList.options[i]; if (opt.value=="") continue;
			// get tiddler, skip missing tiddlers (this should NOT happen)
			var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
			var sel=true;
			if ( (filterStart && tiddler.modified<startDate)
			|| (filterEnd && tiddler.modified>endDate)
			|| (filterTags && !tagged.contains(tiddler.title))
			|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
				sel=false;
			opt.selected=sel;
			count+=sel?1:0;
			total++;
		}
		return count;
	},
	deleteTiddlers: function() {
		var list=$("exportList"); if (!list) return;
		var tids=[];
		for (i=0;i<list.length;i++)
			if (list.options[i].selected && list.options[i].value.length)
				tids.push(list.options[i].value);
		if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
		store.suspendNotifications();
		for (t=0;t<tids.length;t++) {
			var tid=store.getTiddler(tids[t]); if (!tid) continue;
			var msg="'"+tid.title+"' is tagged with 'systemConfig'.\n\n";
			msg+="Removing this tiddler may cause unexpected results.  Are you sure?"
			if (tid.tags.contains("systemConfig") && !confirm(msg)) continue;
			store.removeTiddler(tid.title);
			story.closeTiddler(tid.title);
		}
		store.resumeNotifications();
		alert(tids.length+" tiddlers deleted");
		this.refreshList(0); // reload listbox
		store.notifyAll(); // update page display
	},
	go: function() {
		if (window.location.protocol!="file:") // make sure we are local
			{ displayMessage(config.messages.notFileUrlError); return; }
		// get selected tidders, target filename, target type, and notes
		var list=$("exportList"); if (!list) return;
		var tids=[]; for (var i=0; i<list.options.length; i++) {
			var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
			var tid=store.getTiddler(opt.value); if (!tid) continue;
			tids.push(tid);
		}
		if (!tids.length) return; // no tiddlers selected
		var target = $("exportFilename").value.trim();
		if (!target.length) {
			displayMessage("A local target path/filename is required",target);
			return;
		}
		var filetype = $("exportFormat").value.toLowerCase();
		var notes=$("exportNotes").value.replace(/\n/g,"<br>");
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,notes,total);
		var link="file:///"+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
		}
		var ok=saveFile(target,out);
		displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
	},
	plainTextHeader:
		 '// Source'+':\n//\t%0\n'
		+'// Title:\n//\t%1\n'
		+'// Subtitle:\n//\t%2\n'
		+'// Created:\n//\t%3 by %4\n'
		+'// Application:\n//\tTiddlyWiki %5 / %6 %7\n',
	plainTextTiddler:
		'\n// ----- %0 (by %1 on %2) -----\n\n%3',
	plainTextFooter:
		'',
	newsFeedHeader:
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<channel>\n'
		+'<title>%1</title>\n'
		+'<link>%0</link>\n'
		+'<description>%2</description>\n'
		+'<language>en-us</language>\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<pubDate>%3</pubDate>\n'
		+'<lastBuildDate>%3</lastBuildDate>\n'
		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
	newsFeedTiddler:
		'\n%0\n',
	newsFeedFooter:
		'</channel></rss>',
	pureStoreHeader:
		 '<html><body>'
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'</style>'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'</div>'
		+'<div id="storeArea">',
	pureStoreTiddler:
		'%0\n%1',
	pureStoreFooter:
		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
	assembleFile: function(target,filetype,tids,notes,total) {
		var revised="";
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+"."+version.minor+"."+version.revision;
		var v=version.extensions.ExportTiddlersPlugin; var pver = v.major+"."+v.minor+"."+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,"ExportTiddlersPlugin",pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
				break;
			case this.type_NF: // news feed (XML)
				headerargs[0]=store.getTiddlerText("SiteUrl","");
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
				break;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
				break;
			case this.type_TW: // full TiddlyWiki
			default:
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { displayMessage(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { displayMessage(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+"\n";
				var footer = "\n"+original.substr(posDiv[1]);
				break;
		}
		var out=this.getData(target,filetype,tids);
		var revised = header+convertUnicodeToUTF8(out.join("\n"))+footer;
		// if full TW, insert page title and language attr, and reset all MARKUP blocks...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
			revised=updateLanguageAttribute(revised);
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
			revised=updateMarkupBlock(revised,"PRE-HEAD",
				titles.contains("MarkupPreHead")? "MarkupPreHead" :null);
			revised=updateMarkupBlock(revised,"POST-HEAD",
				titles.contains("MarkupPostHead")?"MarkupPostHead":null);
			revised=updateMarkupBlock(revised,"PRE-BODY",
				titles.contains("MarkupPreBody")? "MarkupPreBody" :null);
			revised=updateMarkupBlock(revised,"POST-SCRIPT",
				titles.contains("MarkupPostBody")?"MarkupPostBody":null);
		}
		total.val=out.length;
		return revised;
	},
	formatItem: function(s,f,t,u) {
		if (f==this.type_TW)
			var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS)
			var r=config.macros.exportTiddlers.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF)
			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX)
			var r=this.plainTextTiddler.format([t.title,t.modifier,t.modified.toLocaleString(),t.text]);
		return r||"";
	},
	getData: function(target,filetype,tids) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText("SiteUrl","");
		for (var i=0; i<tids.length; i++) {
			out.push(this.formatItem(store,filetype,tids[i],url));
			titles.push(tids[i].title);
		}
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			var text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& confirm(this.mergeprompt.format([target]))) {
					var existing=remoteStore.getTiddlers("title");
					for (var i=0; i<existing.length; i++)
						if (!titles.contains(existing[i].title))
							out.push(this.formatItem(remoteStore,filetype,existing[i],url));
					displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
				}
			}
		}
		return out;
	}
}
//}}}
/***
|Name|ExportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.8.4|
|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 ExportTiddlersPlugin|
ExportTiddlersPlugin provides an interactive control panel that allows you to select and extract tiddlers from your ~TiddlyWiki document, and write them into another file, using one of several different file formats:
* ~TiddlyWiki - a complete, stand-alone, standard TiddlyWiki HTML document
* ~PureStore - a small HTML archive file containing tiddler data only (no core code)
* ~PlainText - a simple TXT text file with tiddler source listings
* ~NewsFeed - an XML-format file that can be published for RSS syndication.
!!!!!Usage
<<<
{{{
<<exportTiddlers>> (sidebar menu item)
<<exportTiddlers inline>> (embedded control panel)
}}}

Inline control panel (live):
<<exportTiddlers inline>>

Optional "special tiddlers" used by this plugin:
* SiteUrl<br>URL for official server-published version of document being viewed (used in XML export). Default: //none//
<<<
!!!!!Revisions
<<<
2008.09.29 [2.8.4] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.26 [2.8.3] in go(), if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 [2.8.2] in assembleFile(), make sure that markup block is updated if corresponding Markup* tiddler is exported.
2008.09.19 [2.8.1] in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.11 [2.8.0] extensive code cleanup: moved all global functions inside macro object. Re-wrote file generator and I/O to support TiddlyWiki, PlainText, PureStore, and NewsFeed file formats.  Replaced inline 'match tags' code with use of getMatchingTiddlers() from [[MatchTagsPlugin]] (if installed), with fallback to core getTaggedTiddlers() otherwise.
2008.05.27 [2.7.0] added ability to 'merge' with existing export file.  Also, revised 'matchTags' functionality to be more robust and more efficient
2008.05.12 [2.6.1] automatically add 'export' task to backstage (moved from BackstageTweaks)
2008.03.10 [2.6.0] added "delete tiddlers" button
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.11.10 [2.5.1] removed debugging alert messages from promptForExportFilename()
2007.10.31 [2.5.0] code reduction: removed incomplete/unused interface and supporting functions for exporting directly to http, https or ftp servers.  Plugin now supports exporting to local file only.  Transferring that file is now left to other mechanisms, such as email attachments, FTP uploads, portable media (USB,CD,DVD,...), etc.  Also, updated "save as TiddlyWiki document" output to correctly generate TW2.2 compatible file format.
2007.10.30 [2.4.2] added automatic shadow tiddler definition for [[ExportTiddlers]]
2007.07.16 [2.4.1] in exportTWHeader(), reset HTML source 'markup' so installed markup is NOT copied to new file.
2007.06.30 [2.4.0] added "select related tiddlers" feature.  Recursively scans the tiddler links[] info to find all tiddlers referenced by any of the currently selected tiddler, and then selects them all (including the original tiddlers).  //Theoretically//, selecting all related tiddlers should ensure that the exported file contains all tiddlers needed to properly render all of the originally selected tiddlers.
2007.04.19 [2.3.0] in exportData(), pass SiteURL value as param to saveToRss().  Fixes 'undefined' appearing in tiddler link in XML output.  Also, in refreshExportList(), added 'sort by tags'.  Also, added 'group select'... selecting a heading (date,author,tag) auto-selects all tiddlers in that group.
2007.03.02 [2.2.6] in onClickExportButton(), when selecting open tiddlers for TW2.2, look for "storyDisplay" instead of "tiddlerDisplay" but keep fallback to "tiddlerDisplay" for TW2.1 or earlier
2007.03.01 [2.2.5] removed hijack of store.saveChanges() (was catching save on http:, but there are other solutions that do a much better job of handling save to server.
2006.11.08 [2.2.4] added promptForExportFilename() and replaced type="file" control with edit field + browse button ("...").
2006.10.12 [2.2.3] in exportDIVFooter(), write POST-BODY-START/END markers for compatibility with TW2.1 core file format.  Based on report from Jose Gonzalez.
2006.05.11 [2.2.2] in createExportPanel, removed call to addNotification() to no longer auto-refresh the list every time a tiddler is changed.  Instead, call refreshExportList(0) only when the panel is first rendered and each time it is made visible.  Prevents unneeded feedback messages from being displayed and increases overall document performance, since the listbox is no longer being updated each time a tiddler is saved.
2006.05.02 [2.2.1] Use displayMessage() to show number of selected tiddlers instead of updating listbox 'header' item after each selection.  Prevents awkward 'scroll-to-top' behavior that made multi-select via ctrl-click nearly impossible.  Reported by Paul Reiber.
2006.04.29 [2.2.0] New features: "Notes" are free-form text that is inserted in the header of a TWDIV export file.  When exporting to a server, the "notify" checkbox indicates that server-side script processing should send an email message when the export file is stored on the server.  Comma-separated addresses may be typed in, or pre-defined in the SiteNotify tiddler.
2006.03.29 [2.1.3] added calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.
2006.02.12 [2.1.2] added var to unintended global 'tags' in matchTags(). Avoids FF1501 bug when filtering by tags.  (based on report by TedPavlic)
2006.02.04 [2.1.1] added var to variables that were unintentionally global.  Avoids FireFox 1.5.0.1 crash bug when referencing global variables
2006.02.02 [2.1.0] Added support for output of complete TiddlyWiki documents.  Let's you use ExportTiddlers to generate 'starter' documents from selected tiddlers.
2006.01.21 [2.0.1] Defer initial panel creation and only register a notification function when panel first is created
in saveChanges 'hijack', create panel as needed.  Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.
2005.12.27 [2.0.0] Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
2005.12.24 [0.9.5] Minor adjustments to CSS to force correct link colors regardless of TW stylesheet selection
2005.12.16 [0.9.4] Dynamically create/remove exportPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.
2005.11.15 [0.9.2] added non-Ajax post function to bypass javascript security restrictions on cross-domain I/O.  Moved AJAX functions to separate tiddler (no longer needed here).  Generalized HTTP server to support UnaWiki servers
2005.11.08 [0.9.1] moved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time.  This allows exportPanel to be placed within the same containing element as the "export tiddlers" button, so that relative positioning can be achieved.
2005.10.28 [0.9.0] added 'select opened tiddlers' feature. Based on a suggestion by Geoff Slocock
2005.10.24 [0.8.3] Corrected hijack of 'save changes' when using http:
2005.10.18 [0.8.2] added AJAX functions
2005.10.18 [0.8.1] Corrected timezone handling when filtering for date ranges. Improved error checking/reporting for invalid filter values and filters that don't match any tiddlers. Exporting localfile-to-localfile is working for IE and FF.  Exporting server-to-localfile works in IE (after ActiveX warnings), but has security issues in FF. Cross-domain exporting (localfile/server-to-server) is under development.  More style tweaks, minor text changes and some assorted layout cleanup.
2005.10.17 [0.8.0] First pre-release.
2005.10.16 [0.7.0] filter by tags
2005.10.15 [0.6.0] filter by title/text
2005.10.14 [0.5.0] export to local file (DIV or XML)
2005.10.14 [0.4.0] filter by start/end date
2005.10.13 [0.3.0] panel interaction
2005.10.11 [0.2.0] panel layout
2005.10.10 [0.1.0] code framework
2005.10.09 [0.0.0] development started
<<<
The original design was to be white-painted brick veneer.  The Historic Preservation Commission objects to painting non-historic brick, apparently for reasons of maintenance, so the house will be built of red brick with white highlights, simulating a whitewashed building.  [[Pine Hall "Stonington."|http://www.emorycottage.net/images/stoningtonwhitemortar.jpg]] has been selected.  The bricks have a relatively smooth finish.  The "look" will be one of simplicity that matches the former house as closely as possible within the strictures of the Historic Preservation Commission.

!Paint and Other Colors
# Trim color:		Duron Extra White 7006 over suitable primer
#Brick color:		Pine Hall Stonington (red brick flashed with white)
# Steps: concrete with bullnose treads, framed with brick that matches walls
# Front door color:	Duron Roycroft Copper Red 2839 over suitable primer
# Shutter color:		Duron Roycroft Copper Red 2839 over suitable primer
# Railing color:		White baked-on finish over aluminum (As supplied by manufacturer)
# Gutter color:		White (As supplied by manufacturer)
!Front Entrance
The design includes an arched entryway with Tudor arch and a standard exterior door set back from the arched opening.  

!Terrace and Railings
The front porch, or terrace, will have a floor of stenciled concrete simulating herringbone brick.

I'm told the building code requires railings on the front terrace if it is more than 28" above grade.  The first option should be to adjust the grade to make the terrace 27" above grade.  Where that is not possible, we will install the very plainest baked-on white finished aluminum railings, such as the 600 series by Superior Aluminum: http://www.superioraluminum.com/railings/rail_decorative_photos_600.asp  (No decorative columns; just the railings.)  A supplier in Norcross is Dave Brunelle ( davebrunelle@bellsouth.net ) at Brunelle, Morris, & Associates, (770) 846-0194.

!Driveway and Walk
Concrete steps with bullnose pavers, plain light-gray pervious concrete drive.

!Roof
I wanted to come as close as possible to the red clay tile roof of the original house.  Note that both real clay tile and //faux// tile products require a minimum 3 to 12 pitch.  Maxi Tile P-10 fiber-reinforced cement tile: http://maxitile.com/maxitileroofingproducts.html  is indistinguishable from clay tile until you pick it up.  (It's lighter and stronger.)  The ~DeKalb County Historic Preservation Commission would not approve use of this material for reasons I still do not understand.

I still will retain the terra cotta color, so the roof will be ~Owens-Corning Duration Premium in terra cotta.  http://www.owenscorning.com/around/roofing/shingles/detail.asp?ProdLineListID=60  The roofing material will be ordered the week of January 12.

!Landscaping

I wanted to level the lawn by building a retaining wall in front at the sidewalk and alongside the driveway.  The primary purpose was to make the lawn easy to maintain, but it would also stop mud accumulation on the public sidewalk, which is a real problem we have now addressed.  However, the Historic Preservation Commission objected.  In the end, they approved a 16" to 18" wall deep enough to sit on, and faced with brick veneer matching the house.   Behind the decorative face, the wall should be sturdy enough to last for many years, probably reinforced, poured concrete.

The wall is patterned after Christopher Alexander’s “sitting wall”  as described in //A Pattern Language//:  “… a barrier which separates and a seam which joins at the same time.”  The small wall that is to be built is more seam than barrier, and serves to join more than to separate, connecting the property to the street in a way that the existing steep embankment cannot.  It will be tall enough and deep enough, perhaps 12 to 14 inches to sit upon, with a smooth top.  It will soften the formidable barrier of the existing embankment, encourage children to play on it, and encourage grown-ups to sit, chat, and linger.  The property would be welcoming to pedestrians at its very edge,

Because of fill placed by ~DeKalb County between sidewalk and curb, it will be necessary to raise the sidewalk so that the wall starts three or four inches higher than the current sidewalk grade, which should be a big help in keeping the sidewalk clean.

Use of landscaping rocks and ground cover will make the slope above the wall more-or-less maintenance-free.  The  [[landscape plan|http://www.emorycottage.net/images/Emory_Cottage_Landscape_Plan_20080729.pdf]] specifies liriope ("Big Blue") and day lillies ("Stella.")  A neighbor has suggested adding creeping gardenia to the mix for the pleasant scent in the late spring and early summer.

Although construction will occur within its critical root zone, we will attempt to save the existing magnolia; if that is impossible, it will be replaced by another magnolia.  The existing crape myrtle at the southeast corner of the property will be retained and matched with a new one on the other corner, south of the driveway.

Foundation plantings are a dwarf Burford holly in the niche formed by steps and foundation and "Coral Bell" azaleas in front of the terrace.
The "closed in" feeling of the former house is relieved by a gallery running the length of the house.  In this case, "gallery" is a fancy name for an opened-up hallway.  The front door opens into the gallery through a foyer made necessary by the design of the roof.  Another door opens to the rear patio and garage apron from the back of the gallery.  The gallery is the centerpiece of the house, with all rooms opening onto it.  Living room, dining room, and kitchen connect with wide Tudor-style arches. Pocket doors, generally to be left open, connect the gallery to the anterooms of the master and guest bedrooms on the north.  This provides access to the two bathrooms without the need to enter a bedroom, but also allows for privacy for owner or guests.

!Clerestory Windows
The gallery has a north-facing clerestory running its entire length.  This is one of the two defining features of the house, the other being the Tudor arch theme.  Trim above provides a space for LED rope lighting in addition to the wall sconces.  Because they are effectively inaccessible, the clerestory windows are made of solar protective and self-cleaning glass: Cardinal "Neat" glass: http://www.cardinalcorp.com/products_neat/neat.htm 

!Floor
The gallery floor is "Crema" marble tile.  It fits well with the hardwood floors on either side.
There is a two-car garage at the rear of the house, connected to the kitchen by the laundry room, as shown in the [[floor plan|http://www.emorycottage.net/plans/Emory_Cottage_Floor_plan_20080819.pdf]].  Possibly a suitable paving treatment could make the garage apron double as a patio. Setting the garage doors back is intended to make them “miraculously invisible.”  Access to the patio is though an exterior door at the west end of the gallery.
<<importTiddlers inline>>
----
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
I want to be able to accommodate overnight guests.  The house has a guest bedroom at the northeast corner of the house with a bath that's accessible from the common areas as well as from the guest bedroom.  The guest bedroom has sound insulation in the interior walls.  A ceiling fan keeps air moving when desired.

A pocket door closes off the guest bedroom hall from the gallery.  This allows an overnight guest private access to the guest bathroom while also making it easily accessible to day visitors.
!Heating and Air Conditioning
A gas furnace and air handler are located in a small mechanical room in the garage, making the equipment easily accessible for service.  The air conditioning heat rejector is in the corner formed by the south wall of the kitchen and the east wall of the garage.

!Whole House Ventilation
Forced ventilation is provided by a ducted fan: http://www.wholehousefan.com/superfan.html  Intake vents are in the utility room and the anterooms of the two bedrooms.  The fourth inlet is used to exhaust hot air from the attic.  Exhaust is through the south side of the garage roof.  This system draws outside air through the windows during Atlanta's glorious spring and fall days to provide natural cooling at minimal cost.  The fan is nearly silent, and is located over the garage, not over living space.

!Water Heating
A premium 40-gallon water heater in the garage provides hot water.  Hot water is circulated in a loop by a mechanical pump with timer to offer "instant on" hot water in the morning, and whenever the pump is running.  The hot water loop pipes are insulated to make this an economical feature.
The plugins in this package provide interactive functionality for importing/exporting tiddlers to/from other TiddlyWiki documents.  Additional plugins provide enhanced local/remote file I/O features, including "save as", "save from web" and "upload" functionality.
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.3.3|
|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|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Documentation
<<<
see [[ImportTiddlersPluginInfo]] for details
<<<
!!!!!interactive control panel:
<<<
<<importTiddlers inline>>
{{clear{
^^(see also: [[ImportTiddlers]] shadow tiddler)^^}}}
<<<
!!!!!Installation Notes
<<<
* As of 6/27/2007, "patch" functions that provide backward-compatibility with TW2.1.x and earlier have been split into a separate [[ImportTiddlersPluginPatch]] tiddler to reduce installation overhead for //this// plugin.  You only need to install the additional plugin tiddler when using ImportTiddlersPlugin in documents using TW2.1.x or earlier.
* As of 3/21/2007, the interactive {{{<<importTiddlers>>}}} and non-interactive {{{<<loadTiddlers>>}}} macro definitions and related code have been split into separate [[ImportTiddlersPlugin]] and [[LoadTiddlersPlugin]] to permit selective installation of either the interactive and/or non-interactive macro functions.
* Quick Installation Tip: If you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.
<<<
!!!!!Revisions
<<<
2008.08.12 [4.3.3] rewrite backstage and shadow tiddler definitions for easier customization
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.importTiddlers = {major: 4, minor: 3, revision: 3, date: new Date(2008,8,12)};
//}}}
//{{{
// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers="Use ~TiddlyWiki built-in importer (below) or, ";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers link 'Use ImportTiddlersPlugin control panel...'>>\n";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers core>>";

// use shadow tiddler content in backstage panel
if (config.tasks) config.tasks.importTask.content="<<tiddler ImportTiddlers>>" // TW2.2 or above
//}}}
//{{{
merge(config.macros.importTiddlers,{
	label: "import tiddlers",
	prompt: "Copy tiddlers from another document",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: "%0 tiddler%1 in the list",
	summaryFilteredMsg: "%0 of %1 tiddler%2 in the list",
	plural: "s are",
	single: " is",
	countMsg: "%0 tiddlers selected for import",
	processedMsg: "Processed %0 tiddlers",
	importedMsg: "Imported %0 of %1 tiddlers from %2",
	loadText: "please load a document...",
	closeText: "close",	// text for close button when file is loaded
	doneText: "done",	// text for close button when file is not loaded
	startText: "import",	// text for import button
	stopText: "stop",	// text for import button while importing
	local: true,		// default to import from local file
	src: "",		// path/filename or URL of document to import (retrieved from SiteUrl tiddler)
	proxy: "",		// URL for remote proxy script (retrieved from SiteProxy tiddler)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: "",		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: "",		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ""		// sort order for imported tiddler listbox
});
//}}}
//{{{
// replace core macro handler
if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		document.getElementById("importPanel").style.position="static";
		document.getElementById("importPanel").style.display="block";
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}
//}}}
//{{{
// Handle link click to create/show/hide control panel
function onClickImportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("importPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createImportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}
//{{{
// Create control panel: HTML, CSS
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var panel=document.getElementById("importPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(cmi.css,"importTiddlers");
	panel=createTiddlyElement(place,"span","importPanel",null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
	document.getElementById("importSourceURL").value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
	document.getElementById("importSiteProxy").value=siteProxy;
	cmi.proxy=siteProxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		document.getElementById("fileImportSource").style.display="none";
		document.getElementById("importLocalPanelFix").style.display="block";
	}
	return panel;
}
//}}}
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
	display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\
	background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:100%;margin:0px;font-size:8pt;line-height:110%;}\
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;}\
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:23%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#backstagePanel #importPanel { left:10%; right:auto; }\
';
//}}}
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
	import from\
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
		onclick="onClickImportButton(this,event)" title="show file controls"> local file\
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"\
		onclick="onClickImportButton(this,event)" title="show web controls"> web server\
</td><td align=right>\
	<input type=checkbox class="chk" id="chkImportReport" checked\
		onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
\
<div class="box" id="importSourcePanel" style="margin:.5em">\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->\
enter or browse for source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;document.getElementById(\'importLoad\').onclick()">\
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->\
	<input type="text" id="fileImportSourceFix" style="width:90%"\
		title="Enter a path/file to import"\
		onKeyUp="config.macros.importTiddlers.src=this.value"\
		onChange="config.macros.importTiddlers.src=this.value; document.getElementById(\'importLoad\').onclick()">\
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."\
		title="Select a path/file to import"\
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;\
			document.getElementById(\'fileImportSourceFix\').value=r;\
			config.macros.importTiddlers.src=r;\
			document.getElementById(\'importLoad\').onclick()">\
</div><!--end FF3 FIXUP-->\
</div><!--end local-->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->\
<table><tr><td align=left>\
	enter a URL or <a href="javascript:;" id="importSelectFeed"\
		onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
		select a server</a><br>\
</td><td align=right>\
	<input type="checkbox" class="chk" id="importUsePassword"\
		onClick="config.macros.importTiddlers.usePassword=this.checked;\
			config.macros.importTiddlers.showPanel(\'importIDPWPanel\',this.checked,true);">password\
	<input type="checkbox" class="chk" id="importUseProxy"\
		onClick="config.macros.importTiddlers.useProxy=this.checked;\
			config.macros.importTiddlers.showPanel(\'importSiteProxy\',this.checked,true);">proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
	onKeyUp="config.macros.importTiddlers.proxy=this.value"\
	onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;">\
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>\
username: <input type=text id="txtImportID" style="width:25%" \
	onChange="config.options.txtRemoteUsername=this.value;">\
 password: <input type=password id="txtImportPW" style="width:25%" \
	onChange="config.options.txtRemotePassword=this.value;">\
</div><!--end idpw-->\
</div><!--end http-->\
</div><!--end source-->\
\
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
	onclick="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been added or are different from existing tiddlers">\
	differences</a>\
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
	onclick="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" title="MAXIMIZE/RESTORE list size">\
	&nbsp;=&nbsp;</a>\
</td></tr></table>\
<select id="importList" size=8 multiple\
	onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="text-align:center">\
	<a href="javascript:;"\
		title="click for help using filters..."\
		onclick="alert(\'A filter consists of one or more space-separated combinations of:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>filter</a>\
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"\
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."\
		onfocus="this.select()" value=""\
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"\
		onChange="config.macros.importTiddlers.lastFilter=this.value;">\
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"\
		title="filter list of tiddlers to include only those that match certain criteria"\
		onclick="onClickImportButton(this)">\
	</div>\
</div><!--end select-->\
\
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">\
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked\
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;\
	<input type=checkbox class="chk" id="chkKeepTags" checked\
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;\
	<input type=checkbox class="chk" id="chkAddTags" \
		onClick="config.macros.importTiddlers.addTags=this.checked;\
			config.macros.importTiddlers.showPanel(\'txtNewTags\',this.checked,true);\
			if (this.checked) document.getElementById(\'txtNewTags\').focus();">add tags<br>\
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15\ onfocus="this.select()" \
		title="enter tags to be added to imported tiddlers" \
		onKeyUp="config.macros.importTiddlers.newTags=this.value;\
		document.getElementById(\'chkAddTags\').checked=this.value.length>0;" autocomplete=off>\
	<nobr><input type=checkbox class="chk" id="chkSync" \
		onClick="config.macros.importTiddlers.sync=this.checked;">\
		link imported tiddlers to source document (for sync later)</nobr>\
</div><!--end options-->\
\
<div id="importButtonPanel" style="text-align:center">\
	<input type=button id="importLoad"	class="importButton btn3" value="open"\
		title="load listbox with tiddlers from source document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importOptions"	class="importButton btn3" value="options..."\
		title="set options for tags, sync, etc."\
		onclick="onClickImportButton(this)">\
	<input type=button id="importStart"	class="importButton btn3" value="import"\
		title="start/stop import of selected source tiddlers into current document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importClose"	class="importButton btn3" value="done"\
		title="clear listbox or hide control panel"\
		onclick="onClickImportButton(this)">\
</div>\
\
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">\
	<table><tr><td style="width:65%" align="left">\
		<table><tr><td align=left>\
			tiddler already exists:\
		</td><td align=right>\
			<input type=checkbox class="chk" id="importApplyToAll" \
			onclick="document.getElementById(\'importRename\').disabled=this.checked;"\
			checked>apply to all\
		</td></tr></table>\
		<input type=text id="importNewTitle" size=15 autocomplete=off">\
	</td><td style="width:34%" align="center">\
		<input type=button id="importMerge"\
			class="importButton" style="width:47%" value="merge"\
			title="append the incoming tiddler to the existing tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importSkip"\
			class="importButton" style="width:47%" value="skip"\
			title="do not import this tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><br><input type=button id="importRename"\
			class="importButton" style="width:47%" value="rename"\
			title="rename the incoming tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importReplace"\
			class="importButton" style="width:47%" value="replace"\
			title="discard the existing tiddler"\
			onclick="onClickImportButton(this)">\
	</td></tr></table>\
</div><!--end collision-->\
';
//}}}
//{{{
// process control interactions
function onClickImportButton(which,event)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list = document.getElementById('importList');
	if (!list) return;
	var thePanel = document.getElementById('importPanel');
	var theCollisionPanel = document.getElementById('importCollisionPanel');
	var theNewTitle = document.getElementById('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',document.getElementById('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=="") break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,"URL");
				var d=store.getTiddlerSlice(tids[t].title,"Description");
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,"description");
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						document.getElementById('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						document.getElementById('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show(p,false);
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return(false);
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=="") continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==""||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = "0 selected"
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=document.getElementById('importLastFilter').value;
			cmi.inbound=cmi.filterByHash("#"+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			document.getElementById('importApplyToAll').checked=false;
			document.getElementById('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place == "string") var place=document.getElementById(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,"none"));
	else place.style.display=show?"block":"none";
}
//}}}
//{{{
function refreshImportList(selectedIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list  = document.getElementById("importList");
	if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) 
	{
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,"",false,false);
		list.size=cmi.listsize;

		// toggle buttons and panels
		document.getElementById('importLoad').disabled=false;
		document.getElementById('importLoad').style.display='inline';
		document.getElementById('importStart').disabled=true;
		document.getElementById('importOptions').disabled=true;
		document.getElementById('importOptions').style.display='none';
		document.getElementById('fileImportSource').disabled=false;
		document.getElementById('importFromFile').disabled=false;
		document.getElementById('importFromWeb').disabled=false;
		document.getElementById('importStart').value=cmi.startText;
		document.getElementById('importClose').value=cmi.doneText;
		document.getElementById('importSelectPanel').style.display='none';
		document.getElementById('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	// toggle buttons and panels
	document.getElementById('importLoad').disabled=true;
	document.getElementById('importLoad').style.display='none';
	document.getElementById('importOptions').style.display='inline';
	document.getElementById('importOptions').disabled=false;
	document.getElementById('fileImportSource').disabled=true;
	document.getElementById('importFromFile').disabled=true;
	document.getElementById('importFromWeb').disabled=true;
	document.getElementById('importClose').value=cmi.closeText;
	if (document.getElementById('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!="")
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=""; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	document.getElementById('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,"",false,false);
	list.options[i++]=new Option(((cmi.sort=="title"   )?">":indent)+' [by title]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="modified")?">":indent)+' [by date]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="tags")?">":indent)+' [by tags]',"",false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modified":
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}
//}}}
//{{{
// re-entrant processing for handling import with interactive collision prompting
function importTiddlers(startIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	if (!cmi.inbound) return -1;

	var list = document.getElementById('importList');
	if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status="";
	for (var i=startIndex; i<list.options.length; i++)
		{
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==""))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=="added")
			continue;
		// don't import the "ImportedTiddlers" history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = "";
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=" "+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=" "+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=="")?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields["server.page.revision"]=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields["server.type"]="file";
			inbound.fields["server.host"]=(cmi.local?"file://":"")+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
function importStopped()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	var list = document.getElementById('importList');
	var theNewTitle = document.getElementById('importNewTitle');
	if (!list) return;
	if (cmi.index==-1){ 
		document.getElementById('importStart').value=cmi.startText;
		importReport();		// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		document.getElementById('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if (document.getElementById('importApplyToAll').checked
			&& cmi.lastAction
			&& cmi.lastAction.id!="importRename") {
			onClickImportButton(cmi.lastAction);
		}
	}
}
//}}}
//{{{
function importReport()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	if (!cmi.inbound) return;

	// if import was not completed, the collision panel will still be open... close it now.
	var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';

	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!="skipped") count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text  = ""; }
		// format the report content
		var now = new Date();
		var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
		newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+cmi.src+"|"+cmi.src+"]]:\n";
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += "imported tiddlers were tagged with: \""+cmi.newTags+"\"\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}
	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status="";
	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }
	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g," ")]));
}
//}}}
//{{{
// // File and XMLHttpRequest I/O
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file="";
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf("#"); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp("GET",src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers("title");	
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g," ");
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all = cmi.readTiddlersFromHTML(txt);
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	document.getElementById("importLastFilter").value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers)
{
	var hashpos=src.lastIndexOf("#"); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams("anon",null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case "anon":
			case "open":
				tids.pushUnique(params[p].value);
				break;
			case "tag":
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case "story":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case "search":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}
/***
|Name|ImportTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.3.3|
|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 ImportTiddlersPlugin|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
!!!!!Usage
<<<
{{{<<importTiddlers>>}}} or {{{<<importTiddlers core>>}}}
invokes the built-in importTiddlers macro (TW2.1.x+).  If installed in documents using TW2.0.x or earlier, fallback is to use 'link' display (see below)

{{{<<importTiddlers link label tooltip>>}}}
The ''link'' keyword creates an "import tiddlers" link that when clicked to show/hide import control panel.  ''label'' and ''tooltip'' are optional text parameters (enclosed in quotes or {{{[[...]]}}}, and allow you to override the default display text for the link and the mouseover help text, respectively.

{{{<<importTiddlers inline>>}}}
creates import control panel directly in tiddler content

<<importTiddlers inline>>

Press ''[browse]'' to select a TiddlyWiki document file to import, and then press ''[open]''.  Alternatively, you can type in the path/filename or a remote document URL (starting with http://).  When you have entered the desired source location, press ''[load]'' to retrieve the tiddlers from the remote source.  //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//

Select one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items).  You can press ''[select all]'' to quickly highlight all tiddler titles in the list.  Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time.  When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.

''select: all, new, changes, or differences''

You can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:
>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document
>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)

''Import Tagging:''

Tiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document.  New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.

''Skip, Rename, Merge, or Replace:''

When importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.

To bypass importing this tiddler, press ''[skip]''.  To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''.   Press ''[merge]'' to combine the content from both tiddlers into a single tiddler.  Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.

//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//

''Import Report History''

When tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.

When the import process is completed, the ImportedTiddlers report is automatically displayed for your review.  If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.

If a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.

Note: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.
<<<
!!!!!Revisions
<<<
2008.08.12 [4.3.3] rewrite backstage and shadow tiddler definitions for easier customization
2008.08.05 [4.3.2] rewrote loadRemoteFile() to eliminate use of platform-specific fileExists() function
2008.06.29 [4.3.1] More layout/animation work for simpler sequential interaction.  Code reduction/cleanup
2008.06.28 [4.3.0] HTML and CSS cleanup and tweaks to layout.  Added animation to panels
2008.06.22 [4.2.0] For FireFox, use HTML with separate text+button control instead of type='file' control
2008.06.05 [4.1.0] in filterByHash(), added support for boolean tag expressions using getMatchingTiddlers() (defined by MatchTagsPlugin)
2008.05.12 [4.0.2] automatically tweak the backstage "import" task to add the ImportTiddlers control panel as an optional alternative to the standard import wizard.  (Moved from BackstageTweaks).
2008.04.30 [4.0.1] trim #... suffix for loading files/URLs in IE
2008.04.30 [4.0.0] added source filtering (using URL paramifiers).  Also, abbreviations for code-size reduction.
2008.04.13 [3.9.0] added 'apply to all' checkbox for collision processing
2008.03.26 [3.8.0] added support for selecting pre-defined systemServer URLs
2008.03.25 [3.7.0] added support for setting 'server' fields on imported tiddlers (for later synchronizing of changes)
2008.01.03 [3.6.0] in loadRemoteFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.10.30 [3.5.6] update [[ImportTiddlers]] shadow tiddler definition to include "inline" link, so the plugin control panel is displayed instead of the standard core interface.
2007.06.27 [3.5.5] added missing 'fields' params to saveTiddler() calls.  Fixes problem where importing tiddlers would lose the custom fields.  Also, moved functions for backward-compatibility with TW2.1.x to separate [[ImportTiddlersPluginPatch2.1.x]] tiddler, reducing the size of //this// plugin tiddler by a significant amount.
2007.06.25 [3.5.4] added calls to store.suspendNotifications() and store.resumeNotifications().  Eliminates redisplay processing overhead DURING import activities
2007.04.29 [3.5.3] if refreshImportList() when inbound tiddlers are loaded, change "close" button to "done", and disable certain controls to creates a modal condition, so that actions that reload tiddlers cannot be performed unless "done" is first pressed to end the mode..
2007.04.28 [3.5.2] in handler(), added param support for custom link label/prompt
2007.04.19 [3.5.1] in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content.  Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.03.22 [3.5.0] in refreshImportList(), add handling for 'select section' when a heading is selected.  Makes it really easy to import by tag or date!
2007.03.21 [3.4.0] split loadTiddlers functionality into separate plugin (see [[LoadTiddlersPlugin]])
2007.03.20 [3.3.1] tweak to previous change to allow relative file references via http: (bypasses getLocalPath() so remote URL will be used)
2007.03.20 [3.3.0] added support for local, relative file references: in loadRemoteFile(), check for fileExists().  If not found, prepend relative path location and try again.  Allows use of simple "foo.html" file references with importTiddlers and/or loadTiddlers macros
2007.02.24 [3.2.1] re-labeled control panel "open" button to "load" to avoid confusion with "open" button in system-provided Browse... dialog.  (i.e., "browse, open, open" becomes "browse, open, load")
2007.02.09 [3.2.0] loadTiddlers: added support for "noReload" tag (prevents overwriting existing tiddler, even if inbound tiddler is newer)
2007.02.08 [3.1.3] loadTiddlers: added missing code and documentation for "newTags" handling (a feature change from long, long ago that somehow got lost!)
2006.11.14 [3.1.2] fix macro handler parameter declaration (double-pasted param list corrupts IE)
2006.11.13 [3.1.1] use apply() method to invoke hijacked core handler
2006.11.13 [3.1.0] hijack TW2.1 built-in importTiddlers.handler() so it can co-exist with the plugin interface 'panel'.  Use macro without params (or use 'core' keyword) to display built-in core interface.  Use new "link" param to embed "import tiddlers" link that shows floating panel when clicked.  Renamed a few plugin utility functions so they don't collide with core internal functions.  More code restructuring to come.
2006.10.12 [3.0.8] in readTiddlersFromHTML(), fallback to find end of store area by matching "/body" when POST-BODY-START is not present (backward compatibility for older documents)
2006.09.10 [3.0.7] in readTiddlersFromHTML(), find end of store area by matching "POST-BODY-START" instead of "/body" 
2006.08.16 [3.0.6] Use higher-level store.saveTiddler() instead of store.addTiddler() to avoid conflicts with ZW and other adaptations that hijack low-level tiddler handling.  Also, in CreateImportPanel(), no longer register notify to "refresh listbox after every tiddler change" (left over from old 'auto-filtered' list handling).  Thanks to Bob McElrath for report/solution.
2006.07.29 [3.0.5] added noChangeMsg to loadTiddlers processing.  if not 'quiet' mode, reports skipped tiddlers.
2006.04.18 [3.0.4] in loadTiddlers.handler, fixed parsing of "prompt:" param. Also, corrected parameters mismatch in loadTiddlers() callback function definition (order of params was wrong, resulting in filters NOT being applied)
2006.04.12 [3.0.3] moved many display messages to macro properties for easier L10N translations via 'lingo' definitions.
2006.04.12 [3.0.2] additional refactoring of 'core candidate' code.  Proposed API now defines "loadRemoteFile()" for XMLHttpRequest processing with built in fallback for handling local filesystem access, and readTiddlersFromHTML() to process the resulting source HTML content.
2006.04.04 [3.0.1] in refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section
2006.04.04 [3.0.0] Separate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro.  New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation,  ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers.  Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.
2006.03.30 [2.9.1] when extracting store area from remote URL, look for "</body>" instead of "</body>\n</html>" so it will match even if the "\n" is absent from the source.
2006.03.30 [2.9.0] added optional 'force' macro param.  When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace.  Based on a request from Tom Otvos.
2006.03.28 [2.8.1] in loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (IE does *not* define these values, so we bypass this code)
Also, when extracting store area from remote URL, explicitly look for "</body>\n</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities.  Thanks to Tom Otvos for finding these bugs and suggesting some fixes.
2006.02.21 [2.8.0] added support for "tiddler:TiddlerName" filtering parameter in auto-import processing
2006.02.21 [2.7.1] Clean up layout problems with IE.  (Use tables for alignment instead of SPANs styled with float:left and float:right)
2006.02.21 [2.7.0] Added "local file" and "web server" radio buttons for selecting dynamic import source controls in ImportPanel.  Default file control is replaced with URL text input field when "web server" is selected.  Default remote document URL is defined in SiteURL tiddler.  Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)
2006.02.17 [2.6.0] Removed "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences.  Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.
2006.02.16 [2.5.4] added checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.
2006.02.14 [2.5.3] FF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()
2006.02.10 [2.5.2] corrected unintended global variable in importReport().
2006.02.05 [2.5.1] moved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals
2006.01.18 [2.5.0] added checkbox for "create a report".  Default is to create/update the ImportedTiddlers report.  Clear the checkbox to skip this step.
2006.01.15 [2.4.1] added "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic
2006.01.15 [2.4.0] Added support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax.  Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.
2006.01.15 [2.3.2] Added "ask" parameter to confirm each tiddler before importing (for use with auto-importing)
2006.01.15 [2.3.1] Strip TW core scripts from import source content and load just the storeArea into the hidden IFRAME.  Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins).  Seems to resolve the "Found 0 tiddlers" problem.  Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.
2006.01.12 [2.3.0] Reorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest.  Let's processing continue while waiting for remote hosts to respond to URL requests.  Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source.  Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.
2006.01.11 [2.2.0] Added "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck
2006.01.09 [2.1.1] When a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button.  This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit.  I removed the onChange handling for file input field.  To open a file (local or URL), you must now explicitly press the "open" button in the control panel.
2006.01.08 [2.1.0] IMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements.  Adapted from example code and techniques courtesy of Jonny LeRoy.
2006.01.06 [2.0.2] When refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.
2006.01.04 [2.0.1] When "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.
2005.12.27 [2.0.0] Update for TW2.0
Defer initial panel creation and only register a notification function when panel first is created
2005.12.22 [1.3.1] tweak formatting in importReport() and add 'discard report' link to output
2005.12.03 [1.3.0] Dynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.  Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)
2005.11.29 [1.2.1] fixed formatting of 'detail info' in importReport()
2005.11.11 [1.2.0] added 'inline' param to embed controls in a tiddler
2005.11.09 [1.1.0] only load HTML and CSS the first time the macro handler is called.  Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.
2005.10.25 [1.0.5] fixed typo in importReport() that prevented reports from being generated
2005.10.09 [1.0.4] combined documentation with plugin code instead of using separate tiddlers
2005.08.05 [1.0.3] moved CSS and HTML definitions into plugin code instead of using separate tiddlers
2005.07.27 [1.0.2] core update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()
2005.07.23 [1.0.1] added parameter checks and corrected addNotification() usage
2005.07.20 [1.0.0] Initial Release
<<<
/***
|Name|ImportTiddlersPluginPatch|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPluginPatch|
|Version|4.3.2|
|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|ImportTiddlersPlugin|
|Overrides|config.macros.importTiddlers.handler|
|Description|backward-compatible function patches for use with ImportTiddlersPlugin and TW2.1.x or earlier|
!!!!!Usage
<<<
The current version ImportTiddlersPlugin is compatible with the TW2.2.x core functions.  This "patch" plugin provides additional functions needed to enable the current version of ImportTiddlersPlugin to operate correctly under TW2.1.x or earlier.

{{medium{You do not need to install this plugin if you are using TW2.2.0 or above}}}
(though it won't hurt anything if you do... it will just take up more space).
<<<
!!!!!Revisions
<<<
2008.08.05 [4.3.2] rewrote loadRemoteFile to eliminate use of platform-specific fileExists() function
2008.01.03 [3.6.0] added support for passing txtRemoteUsername and txtRemotePassword for accessing password-protected remote servers
2007.06.27 [3.5.5] compatibility functions split from ImportTiddlersPlugin
|please see [[ImportTiddlersPlugin]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
// these functions are only defined when installed in TW2.1.x and earlier... 
if (version.major+version.minor/10 <= 2.1) {

// Version
version.extensions.importTiddlersPatch21x = {major: 4, minor: 3, revision: 2, date: new Date(2008,8,5)};

// fixups for TW2.0.x and earlier
if (window.merge==undefined) window.merge=function(dst,src,preserveExisting)
	{ for (p in src) if (!preserveExisting||dst[p]===undefined) dst[p]=src[p]; return dst; }
if (config.macros.importTiddlers==undefined) config.macros.importTiddlers={ };

config.macros.importTiddlers.loadRemoteFile = function(src,callback,quiet) {
	if (src==undefined || !src.length) return null; // filename is required
	if (!quiet) clearMessage();
	if (!quiet) displayMessage(this.openMsg.format([src]));

	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,quiet,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var x; // get an request object
		try {x = new XMLHttpRequest()} // moz
		catch(e) {
			try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6
			catch (e) {
				try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5
				catch (e) { return }
			}
		}
		// setup callback function to handle server response(s)
		x.onreadystatechange = function() {
			if (x.readyState == 4) {
				if (x.status==0 || x.status == 200) {
					if (!quiet) displayMessage(config.macros.importTiddlers.readMsg.format([x.responseText.length,src]));
					if (callback) callback(true,quiet,x.responseText,src,x);
				}
				else {
					if (!quiet) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,x.status]));
				}
			}
		}
		// get privileges to read another document's DOM via http:// or file:// (moz-only)
		if (typeof(netscape)!="undefined") {
			try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
			catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
		}
		// send the HTTP request
		try {
			var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
			x.open("GET",src,true,config.options.txtRemoteUsername,config.options.txtRemotePassword);
			if (x.overrideMimeType) x.overrideMimeType('text/html');
			x.send(null);
		}
		catch (e) {
			if (!quiet) {
				displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(unknown)"]));
				displayMessage(e.description?e.description:e.toString());
			}
		}
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html) {
	// for TW2.1 and earlier
	// extract store area from html 
	var start=html.indexOf('<div id="storeArea">');
	var end=html.indexOf("<!--POST-BODY-START--"+">",start);
	if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents
	var sa="<html><body>"+html.substring(start,end)+"</body></html>";

	// load html into iframe document
	var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);
	f=document.createElement("iframe"); f.id="loaderFrame";
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	document.body.appendChild(f);
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open(); d.writeln(sa); d.close();

	// read tiddler DIVs from storeArea DOM element	
	var sa = d.getElementById("storeArea");
	if (!sa) return null;
	sa.normalize();
	var nodes = sa.childNodes;
	if (!nodes || !nodes.length) return null;
	var tiddlers = [];
	for(var t = 0; t < nodes.length; t++) {
		var title = null;
		if(nodes[t].getAttribute)
			title = nodes[t].getAttribute("title"); // TW 2.2+
		if(!title && nodes[t].getAttribute)
			title = nodes[t].getAttribute("tiddler"); // TW 2.1.x
		if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))
			title = nodes[t].id.substr(5); // TW 1.2.x
		if(title && title != "")
			tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));
	}
	return tiddlers;
}

// // COPIED FROM TW2.2beta5
// // enables reading tiddler definitions using TW2.2 storeArea format, even when plugin is running under TW2.1.x
// // storeArea format changes include:
// // <pre> nodes
// // attribute(tiddler) renamed to attribute(title)
// // attribute(modified) is omitted if created==modified
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node)
{
	var e = node.firstChild;
	var text = null;
	if(node.getAttribute("tiddler")) {
		text = getNodeText(e).unescapeLineBreaks();
	} else {
		while(e.nodeName!="PRE" && e.nodeName!="pre") {
			e = e.nextSibling;
		}
		text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
	}
	var modifier = node.getAttribute("modifier");
	var c = node.getAttribute("created");
	var m = node.getAttribute("modified");
	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
	var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
	var tags = node.getAttribute("tags");
	var fields = {};
	var attrs = node.attributes;
	for(var i = attrs.length-1; i >= 0; i--) {
		var name = attrs[i].name;
		if (attrs[i].specified && !TiddlyWiki.isStandardField(name)) {
			fields[name] = attrs[i].value.unescapeLineBreaks();
		}
	}
	tiddler.assign(title,text,modifier,modified,tags,created,fields);
	return tiddler;
};

} // END OF TW2.1.x backward-compatibility functions
//}}}
The kitchen has many cabinets, lots of counter space, and an ample pantry.  I use it for cooking and also for socializing.  Except when entertaining a large number of people, most socializing takes place in the kitchen.  The kitchen is a warm and friendly place, with room to circulate even while meals are being prepared.  This is accomplished with an arched opening into the gallery as well as a smaller arch into the dining room.

There is an ample pantry.  The pantry wall is "blocked"  about 6' off the floor of the south wall for owner-supplied pot racks, so the weight of pots doesn't pull the rack off the wall.

There are good quality counter tops; food preparation areas are Corian and the island and buffet top are Santa Cecelia granite.  Cabinets are Merillat Classic Seneca Ridge, with a dark cherry (Sedona) finish.

The kitchen may be the only area where this matters:  I am left handed and the usual kitchen seems “backwards” to me.  The kitchen is arranged so that preparation flows right-to-left from refrigerator to sink to range to serving area.

The kitchen has a counter top that can be used for buffet service on the north wall and a U-shaped food staging and preparation area on the west, south, and east walls.  Wall cabinets on the north wall have glass fronts.  There is open wine storage under the north wall counter, and also a Vinotemp wine cellar.  Additional open racking for wine storage is on the south wall of the pantry, beneath the pot hooks.

The center island is a single level, with knee space on the west side with two bar stools.  The overhanging granite is supported with corbels.  The ends open, bookshelf-type shelves for cookbooks, etc.

!Appliance and Fixture Schedule:
The appliance schedule is (finally!) final.  Appliances furnished as part of construction are:
* Range, 30" slide-in gas range, stainless with convection oven, [[GE  PGS975SEMSS|http://products.geappliances.com/ApplProducts/Dispatcher?REQUEST=SPECPAGE&SITEID=GEA&SKU=PGS975SEMSS]]
* Over-the-range microwave/convention oven, 30" ducted to outside, [[GE JVM1790SK|http://products.geappliances.com/ApplProducts/Dispatcher?REQUEST=SPECPAGE&SITEID=GEA&SKU=JVM1790SK]]
* Refrigerator, 17.9 cu ft top-freezer stainless w/ ice maker, [[GE  PTS18SHSSS|http://products.geappliances.com/ApplProducts/Dispatcher?REQUEST=SPECPAGE&SITEID=GEA&SKU=PTS18SHSSS]]
* Dishwasher, [[Bosch 300 Series Evolution SHE33M05UC|http://www.boschappliances.com/kitchen-appliances-dishwashers_dishwashers_Evolution_300-series_SHE33M05UC.html]]
* Wine cellar, [[Vinotemp VT-52SN|http://www.vinotemp.com/View.aspx/2874/52-Bottle-Wine-Cooler-with-Front-Exhaust]] 
* Undermount white porcelain on cast iron sink, [[Kohler Langlade® Smart Divide® K-6626-6U-0|http://www.us.kohler.com/onlinecatalog/detail.jsp?prod_num=6626-6U]]

The following equipment was supplied by the owner:
* Washing machine
* Gas dryer
* Bose Wave Radio, 4.5"H x 14"W x 8"D, but needs top access to load CD or operate controls (provide cabinet space with slide-out shelf?)
* Counter-top appliances
** Cuisinart food processor
** Toaster oven
** Coffee maker
** Four-slice toaster
** Knife block
/***
|''Name:''|LegacyStrikeThroughPlugin|
|''Description:''|Support for legacy (pre 2.1) strike through formatting|
|''Version:''|1.0.2|
|''Date:''|Jul 21, 2006|
|''Source:''|http://www.tiddlywiki.com/#LegacyStrikeThroughPlugin|
|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''License:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.0|
***/

//{{{
// Ensure that the LegacyStrikeThrough Plugin is only installed once.
if(!version.extensions.LegacyStrikeThroughPlugin) {
version.extensions.LegacyStrikeThroughPlugin = {installed:true};

config.formatters.push(
{
	name: "legacyStrikeByChar",
	match: "==",
	termRegExp: /(==)/mg,
	element: "strike",
	handler: config.formatterHelpers.createElementAndWikify
});

} //# end of "install only once"
//}}}
[<img[Push-button light switch; first half of 20th Century|http://www.emorycottage.net/images/pb_switch.jpg]][>img[Bronze art deco switch plate|http://www.emorycottage.net/images/switch_plate.gif]] In general, there is a lot of light, particularly in work areas.  Every room has at least one overhead light.  Additional light, as appropriate, comes from floor and table lamps.  Several outlets in the living room are switched so that lighting can be controlled from a single location.

The overall program is to be true to the 1920's nature of the original Emory Cottage in so far as possible using modern fixtures and equipment, while not sacrificing convenience.

The gallery and dining room have push-button switches; these are of modern manufacture, but typical of the first half of the 20th century.  Switches elsewhere are Decora-style rocker switches.  Although "electrical ivory" is used where appropriate to blend with the other decor, most electrical outlets and switches are the "electric brown" of the 20th century.  Switches and receptacles in the common areas of the house have bronze art deco switch plates reflective of the time of the original Emory Cottage.

!Lighting
!!Front Porch and walk.
There is a [[Maxim MX 3091 Tuscan 3 Light Post Light|http://www.maximlighting.com/proddetail.aspx?ItemID=3091FCCH]] between driveway and front steps, adjacent to the front walk.  On the north wall of the terrace, outside the arch, there is a [[Maxim MX 3094 Tuscan 2 Light Outdoor Wall Sconce|http://www.maximlighting.com/proddetail.aspx?ItemID=3094FCCH]].  Beneath the arch is a [[Maxim MX 3098 hanging lantern|http://www.maximlighting.com/proddetail.aspx?ItemID=3098FCCH]].

!!Foyer (Just inside the front door)
One [[Maxim 61601 pendant light|http://www.maximlighting.com/proddetail.aspx?ItemID=61601CLOI]]  in oil-rubbed bronze the center of the foyer.

!!Gallery
Four of [[Maxim MX 20582 Traditional  Wall Washer Sconces|http://www.maximlighting.com/proddetail.aspx?ItemID=20582MROI]] in oil rubbed bronze, two on each side, west of the dining room arch.  In addition, American Lighting ultra-warm white LED rope lighting on a shelf about 12' off the floor, on the north, east, and south walls.

!!Living Room
A [[Hunter Brookline 52' ceiling fan with light|http://www.hunterfan.com/product_detail.aspx?id=12828]] is in the center of the ceiling, and there is a recessed light over the fireplace.  All other lighting comes from floor and table lamps.

!!Dining Room
[>img[Schonbek Trilliane chandelier|http://www.emorycottage.net/images/schonbek_trilliane.jpg]]
There is a dimmable recessed light behind the window seat and a Schonbek Trilliane 40 Light Chandelier suspended from a gilded (with paint, not gold!) dome above the dining room table.  The chandelier is dimmable, and equipped with 40 15-Watt bulbs.


!!Guest Bedroom
*Hallway
A [[Maxim 11171 three-light flush-mount fixture|http://www.maximlighting.com/proddetail.aspx?ItemID=11171EVOI]]
*Bedroom
A [[Hunter Auberville 48' ceiling fan with light|http://www.hunterfan.com/product_detail.aspx?id=12796]] is in the center of the ceiling.  All other lighting comes from floor and table lamps.
*Bath
A [[Maxim 4-light bath vanity light|http://www.maximlighting.com/proddetail.aspx?ItemID=8014MRPC]] in oil-rubbed bronze is mounted over the vanity mirror.  The bathroom is equipped with tile heater and mirror heater.

!!Master Bedroom
*Hallway
A [[Maxim 11171 three-light flush-mount fixture|http://www.maximlighting.com/proddetail.aspx?ItemID=11171EVOI]]
*Bedroom
A [[Hunter Auberville 48' ceiling fan with light|http://www.hunterfan.com/product_detail.aspx?id=12796]] is in the center of the ceiling.  All other lighting comes from floor and table lamps.
*Bath
A [[Maxim 4-light bath vanity light|http://www.maximlighting.com/proddetail.aspx?ItemID=8014MRPC]] in oil-rubbed bronze is mounted over the vanity mirror.  In addition, there is a recessed light within the shower enclosure.  The bathroom is equipped with tile heater and mirror heater.

!!Kitchen
A [[Kichler Ansonia - Island 2 Lt Incandescent|http://www.kichler.com/consumer/products/detail/3849NI]] with bronze finish goes over the island.  Four recessed incandescent lights surround the island and a fifth is places over the sink to provide work lighting.  The pantry has an [["acorn light" |http://www.lowes.com/lowes/lkn?action=productDetail&productId=78755-81378-23503-20&lpage=none]] operated by a switch just inside the door.

!!Laundry
Two four-foot, two lamp fluorescent wrap fixtures, one over the counter and one over the washer/dryer, switched together, plus a recessed fixture over the walking path from garage to house, on a three-way switch that will allow it to be controlled from either door.

!!Garage
Two four-foot, two lamp fluorescent wrap fixtures, one over each parking bay, switched together.

!!Garage exterior
Recessed lights over each garage door, plus three [[Maxim MX 3094 Tuscan 2 Light Outdoor Wall Sconces|http://www.maximlighting.com/proddetail.aspx?ItemID=3094FCCH]], one between the doors and one on either side.

!!Rear Entrance
Recessed light over door.

!~Low-Voltage

The door chime is a Heath/Zenith model 56; it's a "bing-bong" chime, but the cherry finish looks nice and fits the rest of the decor.  It's in the hallway of the master bedroom, which should allow it to be heard almost anywhere.

!!Telephone and Network

Although the equipment is 20th Century, wiring is be for the 21st Century, including fast Ethernet and wireless networking.

I have a very small collection of old telephones that all work, and there are provisions for actually using them.  This means more phone outlets than average.

The telephone demarcation is in the garage south of the laundry room door.  Provide a 3 x 4 plywood backboard, painted white, with standard quad electrical outlet, for mounting equipment, including the demarcation equipment.  Provide a connection to earth ground at the backboard.

Phone/Network Jacks:
* Master bedroom (computer desk): two phone and two network cable
* Master bedroom (night stand): one phone and one network cable under each window (total of two)
* Guest bedroom (night stand):  one phone and one network cable
* Guest bedroom, east window: one phone and one network cable
* Kitchen (wall-mount jack) one phone cable only, metal box attached to stud; no mud rings.
* Kitchen north cabinet counter: one phone and one network cable
* Guest hall closet: Provide a single network jack high up on the south side wall, to be used for a wireless access point.  
* Gallery: one phone jack just inside the master bedroom hallway
* Living room, northeast corner: one phone and one network cable
* Living room, southwest corner: one phone and one network cable
All telephone instruments to be supplied by owner.

Outlets (except kitchen and guest closet) to be combination phone/network outlets rated Category 5 or better for network.

Cable (except kitchen drop) are Belden Dual Cat5 Siamese or equivalent, all pairs connected at wiring closet to a Siemon ~S110AB5-100JP or equivalent punch-block; "printed" jacket to be used for telephone and connected to the bottom or left side, "unprinted" jacket to be network and connected to the corresponding top or right side.  http://www.siemon.com/e-catalog/ECAT_GI_page.aspx?GI_ID=110_s110-modular-jack-wall-mount-blocks

Kitchen drop to be 2-pair UTP 24AWG.  (OK to use a run of Cat5 for this.)  Guest hall closet drop to be a single run of Cat5.  (You can split the Siamese cable and use half for kitchen, other half for closet.)

Wall plates to be single-gang, 2-port Black Box WP460 "electric ivory" or equivalent.  Network jacks to be Black Box FM920  blue or equivalent installed in bottom port of wall plate.  Phone jack to be Black Box USOC jack, FM240, "electric ivory" installed in top port of wall plate.

Network equipment to be provided by owner:
* Siemon surface-mount DSL splitter
* DSL modem (Westell C90)
* Ethernet switching hub (Baystack 70-8T)
* Wireless access point (WAP 54G with IP address fixed and DHCP disabled)
Telephone equipment to be provided by owner:
* Panamax CO line surge suppressor
* Panasonic key telephone unit
* Panasonic voice mail unit
All to be mounted on the telephone/network backboard by owner after house is occupied, except wireless access point, which goes in guest bedroom closet..

The living room should be a place to read and relax, and for friends to gather.  A sofa will face the fireplace, and a wing chair with ottoman will go in the northeast corner, half-facing the sofa. The south wall has built-in book shelves the full width.  Consider having a desk facing outward from the bookshelves.  Other furniture will be added later.  A television outlet is provided in the northeast corner, but is not planned to be used.

A ceiling fan in the geometric center of the room provides a breeze on summer days.
!Fireplace
[>img[Tudor-style fireplace surround|http://emorycottage.net/images/tudormantlesurround.gif]]
The fireplace should be faced with marble, floor to ceiling.  It needs to be framed somehow to give it a finished look, and fitted with a wooden mantle.  I’d like to have a gas lighter and built-in spark screen, or possibly glass doors, or both.  Depending on what we do with the entrance area, a closet which is designed to hold an evening's amount of firewood (or more) plus the various fireplace tools would be nice.

The fireplace itself should reflect the Tudor arch theme. A company in Kennesaw, [[Tudor Artisans|http://www.tudorartisans.com/stonepage.htm]] makes "cast stone" Tudor-themed material, including the fireplace surround that's shown.

!Bookshelves
We need lots of bookshelves in the living room.  My preference is for adjustable shelves in dark stained wood.  Think about a library latter and track.  One source is here: http://www.alacoladder.com/Newfiles/rolladder.htm  It looks like this would cost about $1,200 plus installation and finishing to match bookshelves.

!Entryway
A short wall separates the front door from the living room.  The idea is to make the fireplace a focus of attention and not detract from it with a doorway.
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.2|
|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|macro for automated updates or one-click installations of tiddlers from remote sources|
!!!!!Documentation
>see [[LoadTiddlersPluginInfo]]
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2008.08.05 [3.6.2] rewrote loadFile() to eliminate use of platform-specific fileExists() test
|please see [[LoadTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
version.extensions.loadTiddlers = {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers = {
	label: "",
	tip: "add/update tiddlers from '%0'",
	lockedTag: "noReload",	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: "Please enter a local path/filename or a remote URL",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: "skipped (cancelled by user)",
	loadedMsg: "Loaded %0 of %1 tiddlers from %2",
	reportTitle: "ImportedTiddlers",
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter="updates";
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=="quiet"); if (quiet) params.shift();
		var ask=(params[0]=="confirm"); if (ask) params.shift();
		var force=(params[0]=="force"); if (force) params.shift();
		var init=(params[0]=="init"); if (init) params.shift();
		var noreport=(params[0]=="noreport"); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as "autotags"
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g," ")]),tip.format([src.replace(/%20/g," ")]), function() {
				if (src=="ask") src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=="ask") src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
		if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(unknown)"]));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
				if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp("GET",src,null,null,name,pass,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers("title");	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var noreport=params.noreport;
		var tiddlers = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src.replace(/%20/g," ")]));
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==config.macros.loadTiddlers.reportTitle)
				continue; // skip "ImportedTiddlers" history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!="all") {
				if ((filter=="new") && theExisting) // skip existing tiddlers
					continue;
				if ((filter=="changes") && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=="tag:") && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))
					{ if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g," ")))
				{ tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=Array.concat(inbound.tags,config.macros.loadTiddlers.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?"updated":"added"
			if (init && tags.contains("systemConfig") && !tags.contains("systemConfigDisable")) {
				var ok=true;
				if (ask||!quiet) ok=confirm(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); tiddlers[t].status+=" (plugin initialized)"; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// refresh display
			store.setDirty(true); store.notifyAll();
			// generate a report
			if (!noreport) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g," ")]));
	},
	report: function(src,tiddlers,count,quiet) {
		// format the new report content
		var newText = "On "+(new Date()).toLocaleString()+", ";
		newText += config.options.txtUserName+" loaded "+count+" tiddlers ";
		newText += "from\n[["+src+"|"+src+"]]:\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText="";
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!="")?'\n----\n':"")+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!quiet) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
/***
|Name|LoadTiddlersPluginInfo|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.2|
|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 LoadTiddlersPlugin|
!!!!!Usage
<<<
Syntax:
{{{<<loadTiddlers label:text prompt:text filter source quiet confirm force init noreport tag tag tag...>>}}}

Example:
{{{<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>}}}
<<loadTiddlers "label:load tiddlers from %0" example.html confirm temporary>>

Where:
''"""label:text"""'' and ''"""prompt:text"""''
>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing.  If a label is NOT provided, then no link is created and the loadTiddlers function is performed whenever the containing tiddler is rendered.
''filter'' (optional) determines which tiddlers will be automatically selected for importing.  Use one of the following keywords:
>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.
>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document
>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler
>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)
>''""""tiddler:TiddlerName""""'' retrieves only the specific tiddler named in the parameter.
>''""""tag:text""""'' retrieves only the tiddlers tagged with the indicated text.
>> Note: ''if an existing tiddler is tagged with 'noReload', then it will not be overwritten'', even if the inbound tiddler has been selected by the filtering process.  This allows you to make local changes to imported tiddlers while ensuring that those changes won't be lost due to automatic tiddler updates retrieved from the import source document.
''source'' (required) is the location of the imported document.  It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")
>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked
''"quiet"'' (optional)
>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc).  Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified.  This ensures that changes to your document cannot occur without any visible indication at all.
''"confirm"'' (optional)
>adds interactive confirmation.  A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.
''"init"'' (optional)
>invoke tiddlers tagged with <<tag systemConfig>> as plugins as soon as they are imported, without requiring a save-and-reload action first.  For safety, a browser message box (OK/Cancel) is displayed for each imported plugin, so that you can manually bypass any plugins that you do not want to invoke.  Note, however, that those tiddlers are still //imported// into your document and therefore will still take effect the next time you save-and-reload the document.
''"force"'' (optional)
>import all matching tiddlers, even if unchanged
''"noreport"'' (optional)
>suppress generation of [[ImportedTiddlers]] report
''"tag tag tag..."'' (optional)
>any remaining parameters are used as tag values to be added to each imported tiddler (i.e., "tag-on-import")
<<<
!!!!!Configuration
<<<
__password-protected server settings //(optional, if needed)//:__
>username: <<option txtRemoteUsername>> password: <<option txtRemotePassword>>
>{{{usage: <<option txtRemoteUsername>> <<option txtRemotePassword>>}}}
>''note: these settings are also used by [[ExternalTiddlersPlugin]] and [[ImportTiddlersPlugin]]''
<<<
!!!!!Revisions
<<<
2008.08.05 [3.6.2] rewrote loadFile() to eliminate use of platform-specific fileExists() test
2008.08.03 [3.6.1] in handler(), changed variable 'prompt' to 'tip' to avoid conflict with prompt() function
2008.01.07 [3.6.0] added 'init' option to automatically invoke plugin tiddlers as soon as they are loaded (without needing save/reload)
2008.01.03 [3.5.0] in loadFile(), use lower-level doHttp() instead of loadRemoteFile() in order to support username/password access to remote server
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.27 [3.4.8] added missing 'fields' params to saveTiddler() call. Fixes problem where importing tiddlers would lose the custom fields.
2007.06.25 [3.4.7] add calls to store.suspendNotifications() and store.resumeNotifications() to eliminate redisplay overhead DURING import activities.
2007.05.27 [3.4.6] in handler(),  loadRemoteFile() and doImport(), added 'noreport' flag to suppress generation of ImportedTiddlers
2007.05.27 [3.4.5] in handler(),  initialize 'newTags' to [] (empty array) instead of null... fixes fatal error when loading tiddler without autotagging.
2007.04.22 [3.4.4] in readTiddlersFromHTML(), for TW2.2 and above, use importTiddlyWiki() (new core functionality) to get tiddlers from remote file content.  Also, copied updated TW21Loader.prototype.internalizeTiddler() definition from TW2.2b5 so plugin can read tiddlers from TW2.2+ even when running under TW2.1.x
2007.04.05 [3.4.3] in doImport(), changed this.readTiddlersFromHTML(html) to config.macros.loadTiddlers.readTiddlersFromHTML(html).  Fixes error caused when ImportTiddlersPlugin has NOT been installed along side this plugin.
2007.03.26 [3.4.2] renamed import() to doImport() to fix IE load-time error ("identifier expected").  This may also cause a problem with FF1.5.0.x.... Apparently, "import" is a reserved word in some browsers...
2007.03.22 [3.4.1] code cleanup: moved all functions inside object def'n, re-wrote report function
2007.03.21 [3.4.0] split ImportTiddlersPlugin and LoadTiddlersPlugin functionality into separate plugins
|please see [[ImportTiddlersPluginInfo]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
/***
|Name|LoadTiddlersPluginPatch|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPluginPatch|
|Version|3.6.2|
|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|LoadTiddlersPlugin|
|Overrides||
|Description|backward-compatible function patches for use with LoadTiddlersPlugin and TW2.1.x or earlier|

!!!!!Usage
<<<
The current version LoadTiddlersPlugin is compatible with the TW2.2.x core functions.
This "patch" plugin provides additional functions needed to enable the current version of LoadTiddlersPlugin to operate correctly under TW2.1.x or earlier.

{{medium{You do not need to install this plugin if you are using TW2.2.0 or above}}}
(though it won't hurt anything if you do... it will just take up more space).
<<<
!!!!!Revisions
<<<
2008.08.05 [3.6.2] rewrote loadFile to eliminate use of platform-specific fileExists() function
2008.01.03 [3.5.0] added support for passing txtRemoteUsername and txtRemotePassword for accessing password-protected remote servers
2007.06.27 [3.4.8] compatibility functions split from LoadTiddlersPlugin
|please see [[LoadTiddlersPlugin]] for additional revision details|
2005.07.20 [1.0.0] Initial Release
<<<
!!!!!Code
***/
//{{{
// these functions are only defined when installed in TW2.1.x and earlier... 
if (version.major+version.minor/10 <= 2.1) {

// Version
version.extensions.LoadTiddlersPatch21x = {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers.loadFile = function(src,callback,params) {
	var quiet=params.quiet;
	if (src==undefined || !src.length) return null; // filename is required
	if (!quiet) clearMessage();
	if (!quiet) displayMessage(this.openMsg.format([src]));

	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var x; // get an request object
		try {x = new XMLHttpRequest()} // moz
		catch(e) {
			try {x = new ActiveXObject("Msxml2.XMLHTTP")} // IE 6
			catch (e) {
				try {x = new ActiveXObject("Microsoft.XMLHTTP")} // IE 5
				catch (e) { return }
			}
		}
		// setup callback function to handle server response(s)
		x.onreadystatechange = function() {
			if (x.readyState == 4) {
				if (x.status==0 || x.status == 200) {
					if (!quiet) displayMessage(config.macros.loadTiddlers.readMsg.format([x.responseText.length,src]));
					if (callback) callback(true,params,x.responseText,src,x);
				}
				else {
					if (!quiet) displayMessage(config.macros.loadTiddlers.openErrMsg.format([src,x.status]));
				}
			}
		}
		// get privileges to read another document's DOM via http:// or file:// (moz-only)
		if (typeof(netscape)!="undefined") {
			try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); }
			catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }
		}
		// send the HTTP request
		try {
			var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();
			x.open("GET",src,true,config.options.txtRemoteUsername,config.options.txtRemotePassword);
			if (x.overrideMimeType) x.overrideMimeType('text/html');
			x.send(null);
		}
		catch (e) {
			if (!quiet) {
				displayMessage(this.openErrMsg.format([src,"(unknown)"]));
				displayMessage(e.description?e.description:e.toString());
			}
		}
	}
}

config.macros.loadTiddlers.readTiddlersFromHTML=function(html) {
	// for TW2.1 and earlier
	// extract store area from html 
	var start=html.indexOf('<div id="storeArea">');
	var end=html.indexOf("<!--POST-BODY-START--"+">",start);
	if (end==-1) var end=html.indexOf("</body"+">",start); // backward-compatibility for older documents
	var sa="<html><body>"+html.substring(start,end)+"</body></html>";

	// load html into iframe document
	var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);
	f=document.createElement("iframe"); f.id="loaderFrame";
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	document.body.appendChild(f);
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open(); d.writeln(sa); d.close();

	// read tiddler DIVs from storeArea DOM element	
	var sa = d.getElementById("storeArea");
	if (!sa) return null;
	sa.normalize();
	var nodes = sa.childNodes;
	if (!nodes || !nodes.length) return null;
	var tiddlers = [];
	for(var t = 0; t < nodes.length; t++) {
		var title = null;
		if(nodes[t].getAttribute)
			title = nodes[t].getAttribute("tiddler");
		if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))
			title = nodes[t].id.substr(5);
		if(title && title != "")
			tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));
	}
	return tiddlers;
}

// // COPIED FROM TW2.2beta5
// // enables reading tiddler definitions using TW2.2 storeArea format, even when plugin is running under TW2.1.x
// // storeArea format changes include:
// // <pre> nodes
// // attribute(tiddler) renamed to attribute(title)
// // attribute(modified) is omitted if created==modified
TW21Loader.prototype.internalizeTiddler = function(store,tiddler,title,node)
{
	var e = node.firstChild;
	var text = null;
	if(node.getAttribute("tiddler")) {
		text = getNodeText(e).unescapeLineBreaks();
	} else {
		while(e.nodeName!="PRE" && e.nodeName!="pre") {
			e = e.nextSibling;
		}
		text = e.innerHTML.replace(/\r/mg,"").htmlDecode();
	}
	var modifier = node.getAttribute("modifier");
	var c = node.getAttribute("created");
	var m = node.getAttribute("modified");
	var created = c ? Date.convertFromYYYYMMDDHHMM(c) : version.date;
	var modified = m ? Date.convertFromYYYYMMDDHHMM(m) : created;
	var tags = node.getAttribute("tags");
	var fields = {};
	var attrs = node.attributes;
	for(var i = attrs.length-1; i >= 0; i--) {
		var name = attrs[i].name;
		if (attrs[i].specified && !TiddlyWiki.isStandardField(name)) {
			fields[name] = attrs[i].value.unescapeLineBreaks();
		}
	}
	tiddler.assign(title,text,modifier,modified,tags,created,fields);
	return tiddler;
};

} // END OF TW2.1.x backward-compatibility functions
//}}}
[[News]]
<html><a href="http://www.emorycottage.net/index.xml" onClick="javascript:BBTrackLink('/rss');" rel="alternate"><img src="http://www.emorycottage.net/images/feed-icon-12x12.gif" style="position: relative; top: 1px;" />&nbsp;News via RSS</a></html>
<html><a href="slideshow.html">Construction Pictures</a></html>
<html><a href="construction_recent.html">Recent Pictures Only</a></html>
<html><a href="framing/index.html">Framing Frenzy</a></html>
<html><a href="cabinets/index.html">Cabinet Conundrum</a></html>
[[What's in a Name?]]
[[Program]]
[[Plans]]
[[Living Room]]
[[Kitchen]]
[[Gallery]]
[[Master Bedroom]]
[[Guest Bed and Bath]]
[[Exterior]]
[[Garage]]
[[HVAC]]
[[Lighting and Electrical]]
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-528304-3";
function BBTrackLink(what) {
  if (!urchinTracker) alert("No urchinTracker!");
  result=urchinTracker(what);
  if (!readOnly) alert("Tracking: "+what+"|"+result);
  return true;
}
</script>
<!--{{{-->
<meta name="verify-v1" content="WbdFhtr3nVfqPmWWi0SYJwjDjhY3lpoTu5eMUxx7yh4=" />
<meta name="description" content="Information, plans, and schedules about the cottage being built at 1595 Emory Road in Atlanta." />
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<link rel="shortcut icon" href="/favicon.ico">
<!--}}}-->
The master bedroom is a place to work as well as a sleeping place.  It has a large closet, a work-study area, space for more bookshelves, and a connected bath which is also accessible to the common areas of the house via a small anteroom.

Three large windows face west, and two more face north, so there is plenty of light in the daytime.

I prefer to shower, and so there is shower stall instead of a bath tub.

Because I read at bedtime, switches are arranged to let me control the lights in the master bedroom without getting out of bed.  

[>img[Proposed Front Elevation|http://www.emorycottage.net/images/emory_cottage_elev_v1.gif]] 

''April 28:''  It has been a while since I've written anything.  //I am moved in!//  It's been a struggle, though.  Never, //ever,// try to move without taking time off from work.  Mark the Mover moved the heavy stuff on April 20 and I spent my first night here that night.  I moved everything else over the following week.  Whew!  And, "Howdy, neighbors!  I'm glad to be here!"

''April 17:'' //We have a certificate of occupancy!//  The terrace still needs that surface coating, but the county says I can move in.  We were delayed for two days because the Historic Preservation Commission didn't like the front door, and that's been changed.  The building permit was issued November 17, so it's exactly five months from building permit to certificate of occupancy.  (Of course, it took seven months to get the building permit, and a couple of months to prepare the first application, so the entire project took about 14 months.  The actual construction was the fastest part!)

''April 11:''  //Rain, rain, go away!// We are trying very hard to have the exterior complete before the Druid Hills Tour of Homes next weekend.  Annnnnd... there is rain predicted for Monday and Tuesday.  //~AAaarrgghh!//

We still need to paint the garage floor, build one concrete step in front, and apply the textured surface to the front terrace.  I //really// hope that can happen during the week of the 13th.

''April 7:'' First it was rain; now it's too cold to pour concrete.  Prep work is under way for driveway and sidewalks, with plans to pour concrete on Wednesday.  After that, only a little painting, punch list items and a few landscape details remain.

''April 2:'' You didn't think I was going to post anything on April Fool's Day, did you? {grin}

The rain has absolutely killed the schedule, but we're still slogging forward.  Landscape grading has started and the interior "rough clean" is complete.  I've put half-a-dozen more pictures in the slide shows.

Older "News" postings are available in the NewsArchive Section.

!Older news 
has been moved here to free up some room on the main page.

''March 27:'' We lost almost a whole week because of weather.  Here's the schedule for the coming week:
*Monday, March 30: Final paint; pour concrete for front porch; preliminary cleaning.
*Tuesday: Final paint; brick work on front porch; final electrical work.
*Wednesday: Final paint; brick work on front porch.
*Thursday: Final paint; driveway and sidewalk preparation; final grading.
*Friday: Final paint; driveway and sidewalk; final grading; landscaping.

''March 13:'' We will have another go at paving in the coming two weeks.  Here is the schedule:
*Monday 16:  Grading; final trims; sealing stain grade materials; measure moisture content of floors
*Tuesday:  Pour front porch and rear stoop
*Wednesday:  Begin driveway pavers; finish front porch
*Thursday: Continued paver installation; finish bricking front porch
*Friday: Continued paver installation; driveway prep and forms; trash pick-up; remove T-pole; finish bricking front porch.

''March 5: '' Here is the schedule for the week of March 9:
*Monday, March 9: Grading; install kitchen tops and sink; painting
*Tuesday: Grading; painting; window clean
*Wednesday: Plumbing trim; HVAC trim; interior lockout
*Thursday: Appliances; electrical trim; plumbing trim; lighting
*Friday:  Electrical trim; low voltage trim

''March 2: '' We lost --most of-- more than a day because of snow and ice, but I have no doubt we'll catch up.

''February 26: ''  Most work is still indoors, but paving will start in the coming week.  Here is the schedule:
*Monday, March 2:  Paint; construct bookshelves
*Tuesday: Paint; construct bookshelves
*Wednesday:  Paint; construct bookshelves; forms for driveway
*Thursday: Paint; driveway construction
*Friday: Paint; driveway construction; window clean; bathroom tops.

''February 22: ''  Most activity remains indoors.  Cabinets went in ahead of schedule on Friday and Saturday.  Here's the schedule for the coming week:
*Monday, February 23:  Tile/trim
*Tuesday:  Tile/trim
*Wednesday: Tile/trim
*Thursday:  Prime drywall, touch-up, paint samples
*Friday: Paint
*Saturday: Paint

''February 14: '' The week just ended was spent mostly on dry wall installation.  The masons are finishing up the chimney.  The coming week is dry wall, flooring, and trim.  Here's the schedule:
*Monday, February 16:  Drop trim, sand dry wall
*Tuesday: Install hardwood floors
*Wednesday:  Prime walls and ceiling
*Thursday:  Deliver doors and trim, install trim
*Friday:  Install tile sub floor and walls.

''February 5: '' For people who want to see what's new without going through all the pictures, there's a "Recent Pictures Only" link in the main menu.

Most work in the coming week will be indoors.  Dry wall materials were delivered today, and that's the last "heavy" delivery (except possibly hardwood flooring) until we start landscaping and paving.  

Here's the schedule for next week:
*Monday, February 9:  Hang dry wall 
*Tuesday: Hang dry wall 
*Wednesday:  Float dry wall 
*Thursday:  Float dry wall 
*Friday:  Sand dry wall /Pick up trash
*Saturday: Skim coat dry wall 

''January 31: '' Although there hasn't been much dramatically visible progress, construction has been moving fast.  The most visible (and coolest) change is that the Tudor arch over the entrance has been installed.  Electrical, mechanical, plumbing, and low-voltage rough-in is complete.  Here is the schedule for the week of February 2.  Predicted rainy weather on Monday and Tuesday will likely cause some adjustments.
*Monday, February 2:  Inspection of heating, ventilating, and air conditioning.  Brick laying continues; last bit of roofing installed; exterior painting begins.  Whole-house ventilation system is installed.  
*Tuesday:  Insulation is installed.  Brick laying and roofing are completed; exterior painting continues.
*Wednesday;  Insulation inspection.  Gutters are installed.  Exterior painting continues. 
*Thursday:  Gypsum board (dry wall) material is delivered and installation begins.  Brick cleaning takes place.
*Friday:  Dry wall installation continues.  General cleanup and trash pickup.

The tentative schedule for the week of the 26th is:
*Monday, January 26: Brick laying; HVAC continues; electrical rough-in.
*Tuesday: Brick laying; HVAC; electrical rough-in starts.
*Wednesday: Brick laying; beginning of electrical and mechaincal inspections.
*Thursday: Inspections continue; installation of insulation.
*Friday: Insulation work continues; delivery of gypsum board.

The gypsum board delivery should be the last "heavy" delivery for a while.  We'll have transit-mixed concrete trucks again when we pave the driveway and replace the public sidewalk.  That'll seem like almost nothing; we've placed more than 120 //tons// of concrete already.  (Thanks for putting up with a month of chaos in January!)

''January 20: ''  Cold weather has slowed down the roofing; shingles will break instead of bending if flexed in sub-freezing temperatures.  Even so, there's enough roofing in place to let you see what it's going to look like.  Work on Emory Cottage began with the installation of the permit box on November 19.  We've come a long way in two months!

The revised schedule for this week is:
*Wednesday, January 21: Continue roofing, temperature permitting.  Plumbing rough-in starts.  First load of brick and mortar is delivered.
*Thursday:  Brick laying starts; plumbing rough-in continues.
*Friday: Second load of brick and mortar is delivered; brick laying continues; begin HVAC rough-in.
*Saturday: Brick laying continues.

''January 14: '' Holy smoke!  There's a //house// standing at 1595 Emory Road again.  The prefabricated framing went up fast... less than 20 working hours from delivery to a framed house!  You can read more about it (and see pictures) at FramingFrenzy.  We're ahead of schedule again.  House wrap goes on tomorrow, and windows will be delivered on Friday.  There should be considerably less chaos on Emory Road next week.  The schedule for the week of January 19 looks like this:
*Monday, January 19: Roofing felt and flashing.
*Tuesday: installation of fireplace, begin plumbing rough-in.
*Wednesday &#8211; Friday: Plumbing rough-in.

''January 8: '' The rain slowed things down considerably, but the general contractor worked hard, and we're only about two days behind schedule.  Water and sewer are connected and all grading necessary for construction is complete.  Most excess soil has been removed.  (Some was left for landscaping.)  There will be a gravel drive in place by Friday, and the garage slab should be poured on Friday.  Here is a ''revised'' schedule for the week of January 12:
*Monday, January 12: No work, to allow soil to dry.
*Tuesday: Prefabricated framing panels delivered to site.
*Tuesday &#8211; Thursday: Framing panels erected.
*Friday: Pre-cladding inspection.
By next Friday, there should be something that looks like a house.

''New Year's Day: '' We weren't able to get a required foundation inspection because the county offices are closed Wednesday and Friday.  The brick ledge and waterproofing are complete, but the foundation can't be back filled until it has been inspected, and we're set back a couple of days.  Here is next week's schedule, but it is weather-dependent, and rain is likely for Monday through Wednesday of next week, which will force changes to the schedule below.
*Monday, January 5: Foundation inspection, back fill foundation.
*Tuesday: Water and sewer connections.
*Wednesday: Water and sewer inspection,  back fill water and sewer, begin slab in garage.
*Thursday: Garage form inspection, pour slab for garage.
*Friday: Framing package is delivered.

''December 22: '' The schedule for New Year's week mostly involves unexciting (//i.e.// non-noisy) things.  Hippo Gnu Year!
*Monday December 29:  Waterproofing
*Tuesday:  Drop brick ledge material, begin brick ledge
*Wednesday:  Holiday (Brick ledge construction in the morning, maybe)
*Thursday:  January 1 2009:  Holiday
*Friday:  Holiday (May begin to back-fill foundation walls)
 
''December 19: '' If you want to keep up with the construction schedule, but don't want to visit the Web page every day, you can subscribe to <html><a href="http://www.emorycottage.net/index.xml" onClick="javascript:urchinTracker('/tracking/rss');" rel="alternate">Emory Cottage news via RSS</a></html>.  There's also a link in the menu at the left in case you want to subscribe later.  (RSS is a way for your computer to collect news items passively and display them at a time convenient to you.  If RSS is new to you, you can read more here: <html><a href="http://reviews.digitaltrends.com/guide/35/how-to-use-rss">http://reviews.digitaltrends.com/guide/35/how-to-use-rss</a></html>)

''December 18: '' Here is the construction schedule for Christmas week.  If the weather treats us well, we'll have transit-mix concrete trucks in everyone's way on Tuesday, but Wednesday should be relatively calm.  Merry Christmas, everyone!
*Monday December 22:  Tie wall steel; wall steel inspection; form foundation walls
*Tuesday:   Slump and cylinder tests of concrete, pour walls
*Wednesday:  Strip wall forms
*Thursday: Christmas (Holiday)
*Friday:  Holiday or complete stripping of wall forms

''December 16: '' I have enough photographs to begin to show the progress of construction.  There's a <html><a href="slideshow.html">Construction Pictures</a></html> link in the menu at the left.  (This works much better with Firefox than it does with Internet Exploder.)

''December 10: '' Well, the rain has set the schedule back considerably.  Here's the revised schedule for the week of December 15:
*Monday December 15: Idle to allow soil to dry
*Tuesday:  Dig Footings/Soils Testing
*Wednesday:  Soil Testing/County inspection Pour Footings
*Thursday: Pin Footings (Foundation Survey).  Tie Wall Steel
*Friday:  Wall Steel Inspection/Form Walls

''December 8:'' I have arranged for the framing to be prefabricated off-site and trucked in.  There will be three or four days of chaos on Emory Road as panels arrive and are set in place.  I hope that's easier for the neighbors than the three or more weeks of hammering and sawing that it would take to build the framing in place.

''December 4:'' I have posted the [[plans for Emory Cottage|Plans]] on the Web site.  (Actually, I put 'em out here over a week ago, but I've just realized that I didn't tell anyone.)  A link at the left provides permanent access to the plans and drawings.

''December 1:'' Here is the schedule for the week of December 8:
*Monday, December 8: Surveying/Grading (Rescheduled)
*Tuesday: Grading/Soil Testing and Engineering (Rescheduled)
*Wednesday:  Grading/Drop Form Material/Begin Footing Form (Rescheduled)
*Thursday: Complete Footing Form (Rescheduled)
*Friday: Footing Form Inspection/Pour Footings (Rescheduled)
*Saturday:  Pin/Footing Survey (foundation as built) (Rescheduled)
This schedule is tentative depending upon how quickly the soil dries, and will be updated as the week progresses.

''November 24:'' Here is the work schedule for November 25 through December 5:
*Tuesday, November 25:  Set erosion control perimeters and tree protection fence. (Completed)
*Wednesday, November 26:  Inspection by county of silt fence etc. (Completed)
*Monday, December 1:  Set ~Porta-Toilet and T-pole. (Completed)
*Tuesday, December 2:  ~T-Pole inspection/Tree removal. (Completed)
*Wednesday, December 3:  Finish tree removal/Stake lot. (Completed)
*Thursday/Friday, 4/5:  Rough grading.
''November 17:'' ~DeKalb County issued a building permit for //Emory Cottage// on Tuesday afternoon, November 17th.  It has taken //seven months// since the first drawings were submitted and three months since the last major changes in plans, but, at last, things are moving.  Site preparation will start in November, 2008. {Huzzah!}



I've had a front elevation on this Web page from the start.  Other things were changing so fast that I didn't want to circulate more detailed plans.  What was accurate on one day may have been changed by the next. Now that I have Certificate of Appropriateness and a building permit, it is safe to share. Although there are still minor changes being made, they're things like the location of the water heater.  The major details are (finally!) settled and approved by everyone who has to approve them.

So, here are the plans for //Emory Cottage.//  They're in PDF form, and can be printed out in 8-1/2 x 11 format.  I've put a separate copy of the floor plan here.  It's in the Construction Drawings plan set, too.

*<html><a href="http://www.emorycottage.net/plans/Emory_Cottage_Floor_plan_20080819.pdf" onClick="javascript:urchinTracker('/download/floorplan');">Floor plan</a></html> Version of August 19, 272 KB
*<html><a href="http://www.emorycottage.net/plans/Emory_Cottage_Construction_20080819.pdf" onClick="javascript:urchinTracker('/download/planset');">Construction drawings</a></html>Version of August 19, 1.2 MB
*<html><a href="http://www.emorycottage.net/plans/Emory_Cottage_Landscape_Plan_20080729.pdf" onClick="javascript:urchinTracker('/download/landscapeplan');">Landscape plan</a></html> Version of July 29 752 KB
*<html><a href="http://www.emorycottage.net/plans/Emory_Cottage_Site_Plan_20080520.pdf" onClick="javascript:urchinTracker('/download/siteplan');">Site plan</a></html>  Version of May 20 1.1 MB
//Emory Cottage// replaces a now-demolished 1929 white painted brick bungalow with terra cotta tile roof at the front.  The fa&ccedil;ade of the new house was designed look as much like the previous structure as possible, consistent with current building codes and adding decorative elements appropriate to the style, the neighborhood, and the Historic District.  I wanted white painted brick and terra cotta fiber-cement roof tiles on the new house, effectively duplicating the look of the original, but the Historic Preservation Commission would not approve either.

I spent some time a while back thumbing through architecture books.   I came across a statement of what I wanted in //Villas and Cottages// by Calvert Vaux:

<<<
“...arranged for the use of a man with simple habits, with some refinement of taste.  Such a man would be a lover of hospitality, fond of fresh air, free space, and an easy life, and willing to take advantage of all reasonable modern improvements in the art of living comfortably, but from choice as much as necessity being economical in his requirements, he would have as strong an aversion for empty display as for scanty baldness in arrangement or detail.”
<<<

This seemed to me to be as desirable in 2007, when I set to work to re-plan Emory Cottage, as it was when it was written in 1857.

Rooms in the common areas are connected by Tudor arches, as wide as possible considering placement of furniture and appliances.  This gives the effect of one large room, bright and airy.  The former dark central hallway has been replaced by a gallery with north-facing clerestory windows, a 17' ceiling, and marble tile floor.  Other architectural features are a window seat and gilded dome with chandelier in the dining room and built-in bookcases on the south wall of the living room.  The window seat has turned out to be a magnet for children.

!General
	The shape of the previous house from the front was very pleasing and the new design is nearly identical to the previous one.  The biggest differences as the house appears from the street are that the former screened porch is now enclosed, allowing the chimney to be moved a few feet to the south and a window added between the chimney and the front door. The lot is deep but narrow, so outside focus looks to the front and back, rather than to the sides.  The current elevations and landscape plan address that.

[>img[http://www.emorycottage.net/images/ACF141.jpg]]The  exterioris white  flashed brick (with my thanks to the two neighbors who suggested this solution!) with dark red doors and shutters, matching the original house as closely as possible.   At first I looked at pure white brick, but everything I saw looked like a Krystal or a bank in south Florida.  The idea was a good one even if my approach to it was not, and I finally settled on red brick "flashed" with white in the manufacturing process.  It's [[Pine Hall Stonington,|http://www.pinehallbrick.com/product_gallery/pg_color.cfm?colorID=3&type=0]] in modular size and I've been to see houses made from it.  I am disappointed that the house won't be white painted brick, but neighbors won't be unhappy; Pine Hall Stonington is  pretty nice material.

Exterior trim is to be Duron Extra White 7006 and the door and shutters are to be  [[Duron Roycroft Copper Red 2839|http://www.duron.com/Builders/color/color_palettes.asp#colorPalette_1241]]

Interior colors are cream and melon colors with paprika accents.  (OK, Brown... are you going to paint it or cook it?)  Dark wood finishes are preferable to light or painted wood.  There are hardwood floors throughout, with the exception of the gallery, which is "Crema" marble tile.  The guest bedroom will be a cooler color, possibly cornflower blue or teal.  The overall effect should be like an English hunting print.

The previous house had  Tudor arches between the living and dining rooms, and between the living room and study.  The fireplace opening was also that shape.  It is an unusual and pleasing shape, and the new house retains it as a theme where practical, especially where rooms open into the gallery.  I’d like to have the arches the same thickness as the supporting columns, so that there’s some dimension and substance about them.  It would be appropriate to carry the Tudor arch theme to the arched front doorway. [<img[http://www.emorycottage.net/images/tudor_arch.jpg]]

I have several modest paintings and pictures, and like displaying them.  A gallery with north-facing clerestory windows replaces the former, dark, interior hallway.  Living room, dining room, and kitchen open onto the south side gallery with Tudor arches.  Pocket doors separate bedrooms and bathrooms from the gallery on the north side, making the baths accessible to visitors, but with privacy for owner and overnight guests.

I have a large and increasing assortment of books, both hardbound and paperback that are accommodated by built-in bookshelves in living room.  I don’t have a television set, but do have some simple stereo equipment and enjoy recorded music.  An easy way to provide speaker wire into various rooms would be helpful.  I have a personal computer which will be in the master bedroom.

I enjoy entertaining, and can now accommodate overnight guests better.  This is accomplished with a guest suite of bedroom and bathroom with connecting hallway.

During informal occasions, a lot of socializing takes place in the kitchen, since that’s where I’m likely to be, preparing food and drinks.  An island with sitting spaces accommodates visitors to the kitchen.

The design and construction maintains a general emphasis on durability and ease of maintenance, especially in future years.  I have spent money on quality than quantity.  The example I gave  some years ago was, "no plastic bathtubs."

Because of the proximity to Emory University, there is sometimes a lot of noise outside.  Good acoustical insulation is needed.  (I’ve stayed in a house that had acoustical and thermal insulation in the interior walls as well as the exterior walls, and it seemed much quieter than average.)

There are ceiling fans in the living room and both bedrooms and a [[whole-house ventilation|HVAC]] system for use in the fall and spring.




You can subscribe to "News" from Emory Cottage as an RSS feed.  Point your RSS aggregator here: [[http://www.emorycottage.net/index.xml|http://www.emorycottage.net/index.xml]]
/***
|Name|SaveAsPlugin|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
|Version|2.4.3|
|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|Save current document to a different path/filename|
This plugin automatically adds a 'save as' command to the TiddlyWiki 'backstage' menu that allows you to quickly create an exact copy of the current TiddlyWiki document.  The plugin also defines a macro that you can use to place a "save as..." command link into your sidebar/mainmenu/any tiddler (or wherever you like).
>//Note: This plugin now supersedes [[NewDocumentPlugin]], which has been retired and is no longer being distributed.  In addition, the HTML+CSS "snapshot" functionality previous provided by that plugin has been moved to a separate plugin.  Please see [[SnapshotPlugin]] for additional information.//
!!!!!Documentation
<<<
see [[SaveAsPluginInfo]]
<<<
!!!!!Revisions
<<<
2008.09.29 [2.4.3] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
| Please see [[SaveAsPluginInfo]] for additional revision details |
2006.02.03 [1.0.0] Created.
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveAsPlugin= {major: 2, minor: 4, revision: 2, date: new Date(2008,9,28)};

config.macros.saveAs = {
	label: "save as...",
	labelparam: "label:",
	prompt: "Save current document to a different path/file",
	promptparam: "prompt:",
	filePrompt: "Please select or enter a target path/filename",
	targetparam: "target:",
	defaultFilename: "new.html",
	filenameparam: "filename:",
	currfilekeyword: "here",
	typeparam: "type:",
	type_TW: "tw", type_PS: "ps", type_TX: "tx", type_NF: "nf", // file type tokens
	type_map: { // map filetype param alternatives/abbreviations to token values
		tiddlywiki:"tw", tw:"tw", wiki: "tw",
		purestore: "ps", ps:"ps", store:"ps",
		plaintext: "tx", tx:"tx", text: "tx",
		newsfeed:  "nf", nf:"nf", xml:  "nf", rss:"nf"
	},
	replaceparam: "replace",
	mergeparam: "merge",
	quietparam: "quiet",
	openparam: "open",
	askParam: "ask",
	askMsg: "Enter a tag filter (use * for all tiddlers, 'none' for blank document)",
	emptyParam: "none",
	confirmmsg: "Found %0 tiddlers matching\n\n'%1'\n\nPress OK to proceed",
	mergeprompt: "%0\nalready contains tiddler definitions.\n"
		+"\nPress OK to add new/revised tiddlers to current file contents."
		+"\nPress Cancel to completely replace file contents",
	mergestatus: "Merged %0 new/revised tiddlers and %1 existing tiddlers",
	okmsg: "%0 tiddlers written to %1",
	failmsg: "An error occurred while creating %1",
	filter: "",
	handler: function(place,macroName,params) {
		if (params[0] && params[0].substr(0,this.labelparam.length)==this.labelparam)
			var label=params.shift().substr(this.labelparam.length);
		if (params[0] && params[0].substr(0,this.promptparam.length)==this.promptparam)
			var prompt=params.shift().substr(this.promptparam.length);
		if (params[0] && params[0].substr(0,this.targetparam.length)==this.targetparam)
			var target=params.shift().substr(this.targetparam.length);
		if (params[0] && params[0].substr(0,this.filenameparam.length)==this.filenameparam)
			var filename=params.shift().substr(this.filenameparam.length);
		if (params[0] && params[0].substr(0,this.typeparam.length)==this.typeparam)
			var filetype=this.type_map[params.shift().substr(this.typeparam.length).toLowerCase()];
		var q=(params[0] && params[0]==this.quietparam);   if (q) params.shift();
		var o=(params[0] && params[0]==this.replaceparam); if (o) params.shift();
		var m=(params[0] && params[0]==this.mergeparam);   if (m) params.shift();
		var a=(params[0] && params[0]==this.openparam);    if (a) params.shift();
		var btn=createTiddlyButton(place,label||this.label,prompt||this.prompt,
			function(){config.macros.saveAs.go(
				this.getAttribute('target'),
				this.getAttribute('filename'),
				this.getAttribute('filetype'),
				this.getAttribute('filter'),
				this.getAttribute('quiet')=="true",
				this.getAttribute('overwrite')=="true",
				this.getAttribute('merge')=="true",
				this.getAttribute('autoopen')=="true");  return false;}
		);
		if (target) btn.setAttribute("target",target);
		if (filename) btn.setAttribute("filename",filename);
		btn.setAttribute("filetype",filetype||this.type_TW);
		btn.setAttribute("filter",params.join(" "));
		btn.setAttribute("quiet",q?"true":"false");
		btn.setAttribute("overwrite",o?"true":"false");
		btn.setAttribute("merge",m?"true":"false");
		btn.setAttribute("autoopen",a?"true":"false");
	},
	go: function(target,filename,filetype,filter,quiet,overwrite,merge,autoopen) {
		var cm=config.messages; // abbreviation
		var cms=config.macros.saveAs; // abbreviation
		if (window.location.protocol!="file:") // make sure we are local
			{ displayMessage(cm.notFileUrlError); return; }

		// get tidders, confirm filtered results
		var tids=cms.selectTiddlers(filter);
		if (tids===false) return; // cancelled by user
		if (cms.filter!=cms.emptyParam && cms.filter.length && !quiet)
			if (!confirm(cms.confirmmsg.format([tids.length,cms.filter]))) return;

		// get target path/filename
		if (!filetype) filetype=this.type_TW;
		target=target||cms.getTarget(filename,filetype==this.type_TX?'txt':'html');
		if (!target) return; // cancelled by user

		var link="file:///"+target.replace(/\\/g,'/');
		var samefile=link==decodeURIComponent(window.location.href);
		var p=getLocalPath(document.location.href);
		if (samefile) {
			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
		}
		var notes="";
		var total={val:0};
		var out=this.assembleFile(target,filetype,tids,notes,quiet,overwrite,merge,total);
		var ok=saveFile(target,out);
		if (ok && autoopen) {
			if (!samefile) window.open(link).focus();
			else { store.setDirty(false); window.location.reload(); }
		}
		if (!quiet || !(ok && autoopen))
			displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
	},
	selectTiddlers: function(filter) {
		var cms=config.macros.saveAs; // abbreviation
		cms.filter=filter||"";
		if (filter==cms.emptyParam) return [];
		if (!filter||!filter.length) return store.getTiddlers("title");
		// get filtered tiddlers
		if (filter==config.macros.saveAs.askParam) {
			filter=prompt(config.macros.saveAs.askMsg,"");
			if (!filter) return false;  // cancelled by user
			cms.filter=filter=="*"?"":filter;
			if (filter=="*") return store.getTiddlers("title");
		}
		return store.filterTiddlers("[tag["+filter+"]]");
	},
	getTarget: function(defName,defExt) {
		var cms=config.macros.saveAs; // abbreviation
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		if (!defName||!defName.length) { // use current filename as default
			var p=getLocalPath(window.location.href);
			var s=p.lastIndexOf("/"); if (s==-1) s=p.lastIndexOf("\\"); 
			if (s!=-1) defName=p.substr(s+1);
		}
		var defFilename=(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
		var target=cms.askForFilename(cms.filePrompt,newPath,defFilename,defExt);
		if (!target) return; // cancelled by user
		// if specified file does not include a path, assemble fully qualified path and filename
		var slashpos=target.lastIndexOf("/"); if (slashpos==-1) slashpos=target.lastIndexOf("\\");
		if (slashpos==-1) target=target+(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
		return target;
	},
	askForFilename: function(msg,path,file,defExt) {
		if(window.Components) { // moz
			try {
				netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
				var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
				var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
				picker.init(window, msg, nsIFilePicker.modeSave);
				var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
				thispath.initWithPath(path);
				picker.displayDirectory=thispath;
				picker.defaultExtension=defExt||'html';
				picker.defaultString=file;
				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
				if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
			}
			catch(e) { alert('error during local file access: '+e.toString()) }
		}
		else { // IE
			try { // XP/Vista only
				var s = new ActiveXObject('UserAccounts.CommonDialog');
				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
				s.FilterIndex=(defExt=='txt')?2:3; // default to HTML files;
				s.InitialDir=path;
				s.FileName=file;
				if (s.showOpen()) var result=s.FileName;
			}
			catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
		}
		return result;
	},
	plainTextHeader:
		 '// Source'+':\n//\t%0\n'
		+'// Title:\n//\t%1\n'
		+'// Subtitle:\n//\t%2\n'
		+'// Created:\n//\t%3 by %4\n'
		+'// Application:\n//\tTiddlyWiki %5 / %6 %7\n',
	plainTextTiddler:
		'\n// ----- %0 (by %1 on %2) -----\n\n%3',
	plainTextFooter:
		'',
	newsFeedHeader:
		 '<'+'?xml version="1.0"?'+'>\n'
		+'<rss version="2.0">\n'
		+'<channel>\n'
		+'<title>%1</title>\n'
		+'<link>%0</link>\n'
		+'<description>%2</description>\n'
		+'<language>en-us</language>\n'
		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
		+'<pubDate>%3</pubDate>\n'
		+'<lastBuildDate>%3</lastBuildDate>\n'
		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
	newsFeedTiddler:
		'\n%0\n',
	newsFeedFooter:
		'</channel></rss>',
	pureStoreHeader:
		 '<html><body>'
		+'<style type="text/css">'
		+'	#storeArea {display:block;margin:1em;}'
		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
		+'</style>'
		+'<div id="pureStoreHeading">'
		+'	TiddlyWiki "PureStore" export file<br>'
		+'	Source'+': <b>%0</b><br>'
		+'	Title: <b>%1</b><br>'
		+'	Subtitle: <b>%2</b><br>'
		+'	Created: <b>%3</b> by <b>%4</b><br>'
		+'	TiddlyWiki %5 / %6 %7<br>'
		+'	Notes:<hr><pre>%8</pre>'
		+'</div>'
		+'<div id="storeArea">',
	pureStoreTiddler:
		'%0\n%1',
	pureStoreFooter:
		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
	assembleFile: function(target,filetype,tids,notes,quiet,overwrite,merge,total) {
		var revised="";
		var now = new Date().toLocaleString();
		var src=convertUnicodeToUTF8(document.location.href);
		var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
		var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
		var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
		var twver = version.major+"."+version.minor+"."+version.revision;
		var v=version.extensions.SaveAsPlugin; var pver = v.major+"."+v.minor+"."+v.revision;
		var headerargs=[src,title,subtitle,now,user,twver,"SaveAsPlugin",pver,notes];
		switch (filetype) {
			case this.type_TX: // plain text
				var header=this.plainTextHeader.format(headerargs);
				var footer=this.plainTextFooter;
				break;
			case this.type_NF: // news feed (XML)
				headerargs[0]=store.getTiddlerText("SiteUrl","");
				var header=this.newsFeedHeader.format(headerargs);
				var footer=this.newsFeedFooter;
				break;
			case this.type_PS: // PureStore (no code)
				var header=this.pureStoreHeader.format(headerargs);
				var footer=this.pureStoreFooter;
				break;
			case this.type_TW: // full TiddlyWiki
			default:
				var currPath=getLocalPath(window.location.href);
				var original=loadFile(currPath);
				if (!original) { alert(config.messages.cantSaveError); return; }
				var posDiv = locateStoreArea(original);
				if (!posDiv) { alert(config.messages.invalidFileError.format([currPath])); return; }
				var header = original.substr(0,posDiv[0]+startSaveArea.length)+"\n";
				var footer = "\n"+original.substr(posDiv[1]);
				break;
		}
		var out=this.getData(target,filetype,tids,quiet,overwrite,merge);
		var revised = header+convertUnicodeToUTF8(out.join("\n"))+footer;
		// if full TW, insert page title and language attr, and reset MARKUP blocks as needed...
		if (filetype==this.type_TW) {
			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
			revised=revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
			revised=updateLanguageAttribute(revised);
			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
			revised=updateMarkupBlock(revised,"PRE-HEAD",
				titles.contains("MarkupPreHead")? "MarkupPreHead" :null);
			revised=updateMarkupBlock(revised,"POST-HEAD",
				titles.contains("MarkupPostHead")?"MarkupPostHead":null);
			revised=updateMarkupBlock(revised,"PRE-BODY",
				titles.contains("MarkupPreBody")? "MarkupPreBody" :null);
			revised=updateMarkupBlock(revised,"POST-SCRIPT",
				titles.contains("MarkupPostBody")?"MarkupPostBody":null);
		}
		total.val=out.length;
		return revised;
	},
	formatItem: function(s,f,t,u) {
		if (f==this.type_TW) var r=s.getSaver().externalizeTiddler(s,t);
		if (f==this.type_PS) var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
		if (f==this.type_NF) var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
		if (f==this.type_TX) var r=this.plainTextTiddler.format([t.title,t.modifier,t.modified.toLocaleString(),t.text]);
		return r||"";
	},
	getData: function(target,filetype,tids,quiet,overwrite,merge) {
		// output selected tiddlers and gather list of titles (for use with merge)
		var out=[]; var titles=[];
		var url=store.getTiddlerText("SiteUrl","");
		for (var i=0; i<tids.length; i++) {
			out.push(this.formatItem(store,filetype,tids[i],url));
			titles.push(tids[i].title);
		}
		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
		if (filetype==this.type_TW || filetype==this.type_PS) {
			if (overwrite) return out; // skip merge... forced overwrite
			var text=loadFile(target);
			if (text && text.length) {
				var remoteStore=new TiddlyWiki();
				if (remoteStore.importTiddlyWiki(convertUTF8ToUnicode(text))
					&& (merge||confirm(this.mergeprompt.format([target])))) {
					var existing=remoteStore.getTiddlers("title");
					for (var i=0; i<existing.length; i++)
						if (!titles.contains(existing[i].title))
							out.push(this.formatItem(remoteStore,filetype,existing[i],url));
					if (!quiet) displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
				}
			}
		}
		return out;
	}
};
//}}}
//{{{
// automatically add saveAs to backstage
config.tasks.saveAs = {
	text: "saveAs",
	tooltip: config.macros.saveAs.prompt,
	action: function(){ clearMessage(); config.macros.saveAs.go(); }
}
config.backstageTasks.splice(config.backstageTasks.indexOf("save")+1,0,"saveAs");
//}}}
|Name|SaveAsPluginInfo|
|Source|http://www.TiddlyTools.com/#SaveAsPlugin|
|Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
|Version|2.4.3|
|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 SaveAsPlugin|
This plugin automatically adds a 'save as' command to the TiddlyWiki 'backstage' menu that allows you to quickly create an exact copy of the current TiddlyWiki document.  The plugin also defines a macro that you can use to place a "save as..." command link into your sidebar/mainmenu/any tiddler (or wherever you like).
>//Note: This plugin now supersedes [[NewDocumentPlugin]], which has been retired and is no longer being distributed.  In addition, the HTML+CSS "snapshot" functionality previous provided by that plugin has been moved to a separate plugin.  Please see [[SnapshotPlugin]] for additional information.//
!!!!!Usage
<<<
When the command link is clicked, a standard system-specific dialog box will be displayed so you can select/enter the desired target path and filename.  The default is to create a file called "new.html" in the same directory as the current document.
Syntax:
{{{
<<saveAs "label:..." "prompt:..." "filename:..." "type:..." quiet open tagfilter>>
}}}
where:
*''label:...'' //(optional)//<br>defines alternative link text (replaces default "save as..." display)
*''prompt:...'' //(optional)//<br>defines alternative tooltip text for 'mouseover' prompting (replaces default hard-coded tooltip text)
*''filename:...'' //(optional)//<br>specifies the //default// filename to be shown when asking for an output path/file
*''type:...'' //(optional)//<br>specifies a keyword indicating one of four file output formats:
**''type:~TiddlyWiki'' (or ''wiki'' or ''tw'')<br>a TiddlyWiki HTML document 
**''type:~PureStore'' (or ''store'' or ''ps'')<br>a TiddlyWiki "PureStore" HTML export file (just tiddlers, no core code)
**''type:~PlainText'' (or ''text'' or ''tx'')<br>a plain text file listing of tiddler //source// content
**''type:~NewsFeed'' (or ''xml'' or ''rss'' or ''nf'')<br>an RSS ~NewsFeed XML file
*''quiet'' //(optional)//<br>normally, when using tag filtering (see below), the number of matching tiddlers is reported and you are asked to confirm before saving those tiddlers to a new file.  Use the ''quiet'' keyword to suppress this confirmation step.
*''open'' //(optional)//<br>Use the ''open'' keyword to auto-open the newly created document file in a separate browser tab/window.
*''tagfilter'' or ''ask'' or ''none''//(optional)//<br>You can use the tag filter parameter to select a subset of tiddlers to be written into the new document file.  If you specify a single tag value, then only tiddlers that are tagged with that value are included in the resulting file.  To use a combination of tag values, you can install [[MatchTagsPlugin]], which provides full 'boolean' logic with AND, OR, and NOT operators, as well as nested parentheses, to create complex expressions for filtering and selecting the desired set of tiddlers.  If you specify the keyword, ''ask'' in place of the tagfilter, you will be prompted to enter a tag or tag expression whenever you click on the 'save as...' command link.  Alternatively, you can specify the keyword, ''none'' in place of the tagfilter to omit all tiddlers and create a new //empty// document.
*By default, when no tag filter parameter is provided, all tiddlers in the document are written to the new file.
<<<
!!!!!Examples
<<<
save all tiddlers:
>{{{<<saveAs>>}}}<br>try it: <<saveAs>>
save only tiddlers matching a single tag:
>{{{<<saveAs "label:create Import/Export starter" "filename:TW+ImportExport.html" ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export starter" "filename:TW+ImportExport.html" "ImportExportPackage>>
save to a ~PureStore format:
>{{{<<saveAs "label:create Import/Export archive" "filename:ImportExportPackage.html" type:PureStore open ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export archive" "filename:ImportExportPackage.html" type:PureStore open ImportExportPackage>>
save to a ~PlainText format:
>{{{<<saveAs "label:create Import/Export source listing" type:PlainText open ImportExportPackage>>}}}
>try it: <<saveAs "label:create Import/Export source listing" type:PlainText open ImportExportPackage>>
save tiddlers matching a complex combination of tags (requires [[MatchTagsPlugin]]):
>{{{<<saveAs (alpha or settings) and not systemConfig>>}}}
>try it: <<saveAs (alpha or settings) and not systemConfig>>
prompt for tag or tag expression each time:
>{{{<<saveAs "label:custom save as..." ask>>}}}
>try it: <<saveAs "label:custom save as..." ask>>
<<<
!!!!!Revisions
<<<
2008.09.29 [2.4.3] in getData(), convert existing TW file from UTF8 to Unicode before merging to correct handling of international characters and symbols.
2008.09.28 [2.4.2] in go(), fixed typo that prevented backstage SaveAs from working.
2008.09.24 [2.4.1] if rewriting *current* file and chkSaveBackups and/or chkGenerateAnRssFeed is enabled, then write a backup file or RSS feed, respectively.
2008.09.24 [2.4.0] when 'open' param is used and file is saved to current location, reload() page instead of opening a new tab/window.  Added 'filename' param to specify default filename.  Added 'replace' and 'merge' keyword params to control file handling without asking user.  Improved use of 'quiet' flag to eliminate more unwanted messages.
2008.09.19 [2.3.2] fixed backstage SaveAs command (was defaulting to empty document).  in formatItem(), removed unnecessary convertUnicodeToUTF8() (was causing double-conversion!)
2008.09.16 [2.3.1] fixed IE 'navigate away' error by returning false from button onclick handler
2008.09.11 [2.3.0] added support for alternative file formats: ~PlainText (TX), ~PureStore (PS), or ~NewsFeed (XML) in addition to existing ~TiddlyWiki (TW) document format
2008.09.06 [2.2.1] corrected handling of autoopen attribute so it only applies when "open" param is specified
2008.08.01 [2.2.0] added "open" param to auto-open newly saved document
2008.07.20 [2.1.3] added "quiet" param to bypass confirmation when using tag filter
2008.04.22 [2.1.2] corrected use of getTarget() to check for "user cancelled"
2008.04.22 [2.1.1] documentation fixes
2008.04.22 [2.1.0] added support for tag filtering to completely replace [[NewDocumentPlugin]] (now retired)
2008.04.12 [2.0.1] automatically add "saveAs" to backstage commands
2008.04.12 [2.0.0] initial release based on [[NewDocumentPlugin]]

__Previous revisions from [[NewDocumentPlugin]]__
2008.04.20 [1.8.0] added support for 'noCSS' and 'viewer' params for alternative snapshot output
2008.01.08 [*.*.*] plugin size reduction: documentation moved to ...Info tiddler
2007.12.04 [*.*.*] update for ~TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.03.30 [1.7.0] added support for "print" param as alternative for "snap".  When "print" is used, the filename is ignored and ouput is directed to another browser tab/window, where the print dialog is then automatically triggered.
2007.03.30 [1.6.1] added support for "here" keyword for current tiddler elementID and "prompt:text" param for specifying tooltip text
2007.02.12 [1.6.0] in onClickNewDocument(), reset HTML source 'markup'
2006.10.23 [1.5.1] in onClickNewDocument(), get saved parameter value for snapID instead of using default "contentWrapper" (oops!)
2006.10.18 [1.5.0] new optional param for 'snap'... specify alternative DOM element ID (default is still "contentWrapper").  Based on a suggestion from Xavier Verges.
2006.08.03 [1.4.3] in promptForFilename(), for IE (~WinXP only), added handling for ~UserAccounts.~CommonDialog
2006.07.29 [1.4.2] in onClickNewDocument(), okmsg display is now linked to newly created file
2006.07.24 [1.4.1] in promptForFilename(), check for nsIFilePicker.returnCancel to allow nsIFilePicker.returnOK **OR** nsIFilePicker.returnReplace to be processed.
2006.05.23 [1.4.0] due to very poor performance, support for tag *expressions* has been removed, in favor of a simpler "containsAny()" scan for tags.
2006.04.09 [1.3.6] in onClickNewDocument, added call to convertUnicodeToUTF8() to better handle international characters.
2006.03.15 [1.3.5] added nsIFilePicker() handler for selecting filename in moz-based browsers.  IE and other non-moz browsers still use simple prompt() dialog
2006.03.15 [1.3.0] added "label:text" param for custom link text.  added special "all" filter parameter for "save as..." handling (writes all tiddlers to output file)
2006.03.09 [1.2.0] added special "snap" filter parameter to generate and write "snapshot" files containing static HTML+CSS for currently rendered document.
2006.02.24 [1.1.2] Fix incompatiblity with TW 2.0.5 by removing custom definition of getLocalPath() (which is now part of TW core)
2006.02.03 [1.1.1] concatentate 'extra' params so that tag expressions don't have to be quoted.   moved all text to 'formatted' string definitions for easier translation.
2006.02.03 [1.1.0] added support for tag EXPRESSIONS.  plus improved documentation and code cleanup
2006.02.03 [1.0.0] Created.
<<<
/***
|Name|SaveFromWebConfig|
|Source|http://www.TiddlyTools.com/#SaveFromWebConfig|
|Documentation|http://www.TiddlyTools.com/#SaveFromWebPluginInfo|
|Version|1.3.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|configuration settings for SaveFromWebPlugin|
***/
/***
!!!!! URL for server-side 'reflector' script.
***/
//{{{
config.options.txtSaveFromWebScriptURL="savefromweb.php";
//}}}
/***
>Script can be hosted on ANY web server that supports PHP5.
***/
/***
!!!!! URL for TiddlyWiki core source
//{{{
config.options.txtSaveFromWebSourceFile="http://www.TiddlyTools.com/empty.html";
//}}}
/***
>use alternative document URL for retrieving TiddlyWiki core source code. Using an *empty* TW minimizes data transfer for retrieving TW core. Can be on ANY domain... If blank, retrieve core source code from current document URL.
***/
/***
!!!!! Target filename
//{{{
config.options.txtSaveFromWebTargetFilename="";
//}}}
/***
>specifies the desired destination filename for the downloaded file. Can be any valid filename for local filesystem and will appear as the default value when you are prompted to save the file.  If blank, plugin uses the filename from the URL of the current document (or the domain name if there is no filename in the URL)
***/
/***
!!!!! Pre-fetch option:
//{{{
config.options.chkSaveFromWebPreFetch=false;
//}}}
/***
<<<
* true=get (and cache) TW core code when document is first loaded (i.e., when plugin is initialized)
* false=get and cache core code the first time the file is being saved
This option causes the plugin to retrieve the TiddlyWiki core source as soon as you load the document, instead of waiting for the first time you save.  This ensures that the TiddlyWiki core source can still be saved to the local filesystem even if your network connection is dropped before you save your changes.  Note that, even without pre-fetching, the core source is always cached after it is retrieved, so that subsequent saves don't do extra work to get it again.
<<<
***/
/***
!!!!! Local I/O option
//{{{
config.options.chkSaveFromWebAttemptLocalIO=false;
//}}}
/***
<<<
(requires browser security permissions, i.e., "trusted site" settings).
The plugin will try to obtain security permission for direct filesystem I/O.  If you grant filesystem access to the script, then it writes the document directly to your filesystem, and doesn't use the server-side reflector script at all.  This allows you to save a remote file to your local filesystem, even if your net connection drops after you open the document. Note: if filesystem permissions are not granted, the plugin will automatically attempt to use the server-side reflector script as a fallback... even if no longer connected to the net.
<<<
***/
/***
|Name|SaveFromWebPlugin|
|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|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|extend 'save changes' to get remote document contents and save to local filesystem |
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.//
!!!!!Documentation
>see [[SaveFromWebPluginInfo]]
!!!!!Configuration
> see [[SaveFromWebConfig]]
!!!!!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.
|please see [[SaveFromWebPluginInfo]] for additional revision details|
2007.06.26 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.SaveFromWebPlugin= {major: 1, minor: 3, revision: 1, date: new Date(2008,9,29)};
//}}}

//{{{
// DEFAULT SETTINGS
if (config.options.txtSaveFromWebScriptURL==undefined)
	config.options.txtSaveFromWebScriptURL="savefromweb.php";
if (config.options.txtSaveFromWebTargetFilename==undefined)
	config.options.txtSaveFromWebTargetFilename=""; // use current filename when blank
if (config.options.txtSaveFromWebSourceFile==undefined)
	config.options.txtSaveFromWebSourceFile=""; // use current URL when blank
if (config.options.chkSaveFromWebAttemptLocalIO==undefined)
	config.options.chkSaveFromWebAttemptLocalIO=true; // true=try to use local filesystem I/O (requires security permissions)
if (config.options.chkSaveFromWebPreFetch==undefined)
	config.options.chkSaveFromWebPreFetch=false; // true=retrieve TW core when document is first loaded
//}}}

//{{{
// OPTIONAL: get TW core source code when plugin is loaded (i.e., once per document session)
if (document.location.protocol!="file:" && config.options.chkSaveFromWebPreFetch) {
	// retrieve TW source from server...
	var src=document.location.href;
	if (config.options.txtSaveFromWebSourceFile && config.options.txtSaveFromWebSourceFile.length)
		src=config.options.txtSaveFromWebSourceFile;
	var target=config.options.txtSaveFromWebTargetFilename;
	if (!target.length) { // use current filename
		var loc=document.location.pathname;
		var slashpos=loc.lastIndexOf("/");
		target=(slashpos==-1)?loc:loc.substr(slashpos+1);
		if (!target.length) target=document.location.host+".html";
	}
	var xhr=loadRemoteFile(src,function(success,target,txt,src,xhr){if(success)config.saveFromWebSourceCache=txt;},target);
}
//}}}

//{{{
window.saveFromWeb_saveChanges = window.saveChanges;
window.saveChanges = function(onlyIfDirty,tiddlers) {
	// if on file:, just use standard core save handling
	if(document.location.protocol == "file:") { window.saveFromWeb_saveChanges.apply(this,arguments); return; }
	clearMessage();
	// get target filename
	var target=config.options.txtSaveFromWebTargetFilename;
	if (!target.length) { // use current filename
		var loc=document.location.pathname;
		var slashpos=loc.lastIndexOf("/");
		target=(slashpos==-1)?loc:loc.substr(slashpos+1);
		if (!target.length) target=document.location.host+".html";
	}
	// get TW core source location
	var src=document.location.href;
	if (config.options.txtSaveFromWebSourceFile && config.options.txtSaveFromWebSourceFile.length)
		src=config.options.txtSaveFromWebSourceFile;
	// if core source has already been cached, go straight to saving the file...
	if (config.saveFromWebSourceCache)
		{ window.saveFromWeb(true,target,config.saveFromWebSourceCache,src,null); return; }
	// otherwise, retrieve TW source from server...
	displayMessage("Retrieving TiddlyWiki core from "+src);
	var xhr=loadRemoteFile(src,window.saveFromWeb,target);
	if (!xhr) { // couldn't load remote, report core error message
		displayMessage("Could not retrieve TiddlyWiki core... download unsuccessful.");
		alert(config.messages.notFileUrlError);
		if(store.tiddlerExists(config.messages.saveInstructions))
			story.displayTiddler(null,config.messages.saveInstructions);
	}
	return;
}
//}}}

//{{{
window.saveFromWeb = function(success,target,txt,url,xhr) {
	if(!success) {
		displayMessage("Could not retrieve TiddlyWiki core... download unsuccessful.");
		alert(config.messages.cantSaveError);
		if(store.tiddlerExists(config.messages.saveInstructions))
			story.displayTiddler(null,config.messages.saveInstructions);
		return;
	}
	// Locate the storeArea div's in the original source
	var posDiv=locateStoreArea(txt);
	if(!posDiv) { alert(config.messages.invalidFileError.format([url])); return; }

	// cache the document source so subsequent saves don't have to retrieve the source each time
	if (!config.saveFromWebSourceCache) config.saveFromWebSourceCache=txt;

	// if we can get local filesystem access, then ask for a filename and merge/write the file
	if (config.options.chkSaveFromWebAttemptLocalIO) {
		try {
			// get local target path+filename (may be blocked by browser security)
			var target=promptForFilename( "Save file as:","C:\\",target,"html");
			if (!target || !target.length) return;
			saveBackup(target,txt);
			saveRss(target);
			saveEmpty(target,txt,posDiv);
			saveMain(target,txt,posDiv);
			return;
		} catch(e) { }
	}
	// otherwise, fallback to using online 'reflector' script (if any)
	if (config.options.txtSaveFromWebScriptURL.length) {
		displayMessage("Merging tiddlers with core and preparing for download...");
		var merged=txt.substr(0,posDiv[0]+startSaveArea.length)+"\n"+
			store.allTiddlersAsHtml()+"\n"+txt.substr(posDiv[1]);
		var title=getPageTitle().htmlEncode();
		merged=merged.replaceChunk("<title"+">","</title"+">"," "+title+" ");
		merged=updateLanguageAttribute(merged);
		merged=updateMarkupBlock(merged,"PRE-HEAD","MarkupPreHead");
		merged=updateMarkupBlock(merged,"POST-HEAD","MarkupPostHead");
		merged=updateMarkupBlock(merged,"PRE-BODY","MarkupPreBody");
		merged=updateMarkupBlock(merged,"POST-SCRIPT","MarkupPostBody");
		// create form in a hidden frame and submit it to server
		var html='<input type="hidden" name="filename" value="">'
			+'<input type="hidden" name="contents" value="">';
		var form=window.createHiddenForm(config.options.txtSaveFromWebScriptURL,html);
		form.filename.value=target;
		form.contents.value=merged;
		form.submit();
	}
}
//}}}

//{{{
window.createHiddenForm=function(action,body) {
	var f=document.getElementById("saveFromWebFrame");
	if (f) document.body.removeChild(f);
	var f=createTiddlyElement(document.body,"iframe","saveFromWebFrame");
	f.style.width="0px"; f.style.height="0px"; f.style.border="0px";
	var d=f.document;
	if (f.contentDocument) d=f.contentDocument; // For NS6
	else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6
	d.open();
	d.writeln('<form target="_self" action="'+action+'" method="post" enctype="multipart/form-data">'+body+'</form>');
	d.close();
	return d.getElementsByTagName("form")[0];
}
//}}}

//{{{
// note: if blocked by browser security, this function will throw an error...
// the CALLING function should use "try{...} catch(e){...}" to handle the security errors
window.promptForFilename=function(msg,path,file,defext) {
	var result="";
	if(window.Components) { // moz
		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
		var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
		picker.init(window, msg, nsIFilePicker.modeSave);
		picker.displayDirectory=null;
		picker.defaultExtension=defext;
		picker.defaultString=file;
		picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
		if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
	}
	else { // IE (XP only)
		var s = new ActiveXObject('UserAccounts.CommonDialog');
		s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
		s.FilterIndex=1; // default to ALL files;
		s.InitialDir=path;
		s.FileName=file;
		if (s.showOpen()) var result=s.FileName;
	}
	return result;
}
//}}}
|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
<<<
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY">><<importTiddlers link>><<exportTiddlers>><<saveChanges>><<saveAs>><<upload>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
Rebuilding the Cottage at 1595 Emory Road
Emory Cottage<html><img src="images/logotype.png" style="zIndex: 20; position: absolute; top:0; left: 0; " alt="Emory Cottage"/></html>
http://www.EmoryCottage.net
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}

/***
|Name|TemporaryTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#TemporaryTiddlersPlugin|
|Version|1.1.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|plugin|
|Requires||
|Overrides|SaverBase.prototype.externalize()|
|Options|##Configuration|
|Description|blocks tiddlers tagged with "temporary" from being saved into the TW file|
!!!!!Usage
<<<
When the TW document is saved (either to local disk or remote URL), any tiddlers tagged with "temporary" will be skipped over, so that they are not written to the file.  To keep a temporary tiddler, simply edit it and remove the tag before saving the file.  This feature can be combined with various plugins that can automatically create new tiddlers, such as [[SearchOptionsPlugin]] ([[SearchResults]]) and [[ImportTiddlersPlugin]] ([[ImportedTiddlers]]) so that these transient results are not retained when you save you document.

You can also use this tag with the {{{<<loadTiddlers>>}}} macro and the //auto-tagging// features provided by [[ImportTiddlersPlugin]], so that each time you open your document, you can automatically retrieve an up-to-date set of common tiddlers that are stored in another document (either local or via remote URL), without those tiddlers being retained when you save your document.
<<<
!!!!!Configuration
<<<
When saving the document:
<<option chkTemporaryQuiet>> Suppress reporting of temporary tiddlers that have not been saved
<<option chkTemporaryKeep>> Keep temporary tiddlers (i.e., ignore the 'temporary' tag)
Enter a tag value to use when marking tiddlers as temporary: <<option txtTemporaryTag>>
<<<
!!!!!Revisions
<<<
2008.04.08 [1.1.1] don't automatically add configuration options to AdvancedOptions tiddler
2008.03.01 [1.1.0] added support for recognizing 'temporary' flag stored as a tiddler *field* (as an optional alternative to using a tag)
2007.02.08 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.TemporaryTiddlersPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2008,4,8)};

// configuration defaults
if (config.options.chkTemporaryKeep ==undefined) config.options.chkTemporaryKeep =false;
if (config.options.chkTemporaryQuiet==undefined) config.options.chkTemporaryQuiet=false;
if (config.options.txtTemporaryTag==undefined) config.options.txtTemporaryTag="temporary";
// lingo
config.messages.TemporaryWarning = "'%0' ...temporary tiddler not saved";
// core override
SaverBase.prototype.externalize = function(store) 
{
	var results = [];
	var tiddlers = store.getTiddlers("title");
	for (var t = 0; t < tiddlers.length; t++) {
		if (config.options.chkTemporaryKeep||!(tiddlers[t].fields['temporary']||tiddlers[t].isTagged(config.options.txtTemporaryTag)))
			results.push(this.externalizeTiddler(store, tiddlers[t]));
		else if (!config.options.chkTemporaryQuiet) // notify user that tiddler won't be saved
			displayMessage(config.messages.TemporaryWarning.format([tiddlers[t].title]));
	}
	return results.join("\n");
}
//}}}
One possibility for tile is something like this: http://flooring.builddirect.com/Travertine-Tile/antiquetile-Walnut/ProductDisplay_7246_P1_10008777.aspx  This might actually be pretty nice in the gallery area, too.
/***
<<tiddler UploadPluginDoc>>
!Code
***/
//{{{
version.extensions.UploadPlugin = {
 major: 3, minor: 3, revision: 1, 
 date: new Date(2006,3,30),
 type: 'macro',
 source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
 docs: 'http://tiddlywiki.bidix.info/#UploadPluginDoc'
};
//}}}

////+++!![config.lib.file]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.file) config.lib.file= {
 author: 'BidiX',
 version: {major: 0, minor: 1, revision: 0}, 
 date: new Date(2006,3,9)
};
config.lib.file.dirname = function (filePath) {
 var lastpos;
 if ((lastpos = filePath.lastIndexOf("/")) != -1) {
 return filePath.substring(0, lastpos);
 } else {
 return filePath.substring(0, filePath.lastIndexOf("\\"));
 }
};
config.lib.file.basename = function (filePath) {
 var lastpos;
 if ((lastpos = filePath.lastIndexOf("#")) != -1) 
 filePath = filePath.substring(0, lastpos);
 if ((lastpos = filePath.lastIndexOf("/")) != -1) {
 return filePath.substring(lastpos + 1);
 } else
 return filePath.substring(filePath.lastIndexOf("\\")+1);
};
window.basename = function() {return "@@deprecated@@";};
//}}}
////===

////+++!![config.lib.log]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.log) config.lib.log= {
 author: 'BidiX',
 version: {major: 0, minor: 1, revision: 0}, 
 date: new Date(2006,3,9)
};
config.lib.Log = function(tiddlerTitle, logHeader) {
 if (version.major < 2)
 this.tiddler = store.tiddlers[tiddlerTitle];
 else
 this.tiddler = store.getTiddler(tiddlerTitle);
 if (!this.tiddler) {
 this.tiddler = new Tiddler();
 this.tiddler.title = tiddlerTitle;
 this.tiddler.text = "| !date | !user | !location |" + logHeader;
 this.tiddler.created = new Date();
 this.tiddler.modifier = config.options.txtUserName;
 this.tiddler.modified = new Date();
 if (version.major < 2)
 store.tiddlers[tiddlerTitle] = this.tiddler;
 else
 store.addTiddler(this.tiddler);
 }
 return this;
};

config.lib.Log.prototype.newLine = function (line) {
 var now = new Date();
 var newText = "| ";
 newText += now.getDate()+"/"+(now.getMonth()+1)+"/"+now.getFullYear() + " ";
 newText += now.getHours()+":"+now.getMinutes()+":"+now.getSeconds()+" | ";
 newText += config.options.txtUserName + " | ";
 var location = document.location.toString();
 var filename = config.lib.file.basename(location);
 if (!filename) filename = '/';
 newText += "[["+filename+"|"+location + "]] |";
 this.tiddler.text = this.tiddler.text + "\n" + newText;
 this.addToLine(line);
};

config.lib.Log.prototype.addToLine = function (text) {
 this.tiddler.text = this.tiddler.text + text;
 this.tiddler.modifier = config.options.txtUserName;
 this.tiddler.modified = new Date();
 if (version.major < 2)
 store.tiddlers[this.tiddler.tittle] = this.tiddler;
 else {
 store.addTiddler(this.tiddler);
 story.refreshTiddler(this.tiddler.title);
 store.notify(this.tiddler.title, true);
 }
 if (version.major < 2)
 store.notifyAll(); 
};
//}}}
////===

////+++!![config.lib.options]

//{{{
if (!config.lib) config.lib = {};
if (!config.lib.options) config.lib.options = {
 author: 'BidiX',
 version: {major: 0, minor: 1, revision: 0}, 
 date: new Date(2006,3,9)
};

config.lib.options.init = function (name, defaultValue) {
 if (!config.options[name]) {
 config.options[name] = defaultValue;
 saveOptionCookie(name);
 }
};
//}}}
////===

////+++!![PasswordTweak]

//{{{
version.extensions.PasswordTweak = {
 major: 1, minor: 0, revision: 2, date: new Date(2006,3,11),
 type: 'tweak',
 source: 'http://tiddlywiki.bidix.info/#PasswordTweak'
};
//}}}
/***
!!config.macros.option
***/
//{{{
config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordType = "password"; // password | text

config.macros.option.onChangeOption = function(e)
{
 var opt = this.getAttribute("option");
 var elementType,valueField;
 if(opt) {
 switch(opt.substr(0,3)) {
 case "txt":
 elementType = "input";
 valueField = "value";
 break;
 case "pas":
 elementType = "input";
 valueField = "value";
 break;
 case "chk":
 elementType = "input";
 valueField = "checked";
 break;
 }
 config.options[opt] = this[valueField];
 saveOptionCookie(opt);
 var nodes = document.getElementsByTagName(elementType);
 for(var t=0; t<nodes.length; t++) {
 var optNode = nodes[t].getAttribute("option");
 if (opt == optNode) 
 nodes[t][valueField] = this[valueField];
 }
 }
 return(true);
};

config.macros.option.handler = function(place,macroName,params)
{
 var opt = params[0];
 var size = 15;
 if (params[1])
 size = params[1];
 if(config.options[opt] === undefined) {
 return;}
 var c;
 switch(opt.substr(0,3)) {
 case "txt":
 c = document.createElement("input");
 c.onkeyup = this.onChangeOption;
 c.setAttribute ("option",opt);
 c.size = size;
 c.value = config.options[opt];
 place.appendChild(c);
 break;
 case "pas":
 // input password
 c = document.createElement ("input");
 c.setAttribute("type",config.macros.option.passwordType);
 c.onkeyup = this.onChangeOption;
 c.setAttribute("option",opt);
 c.size = size;
 c.value = config.options[opt];
 place.appendChild(c);
 // checkbox link with this password "save this password on this computer"
 c = document.createElement("input");
 c.setAttribute("type","checkbox");
 c.onclick = this.onChangeOption;
 c.setAttribute("option","chk"+opt);
 place.appendChild(c);
 c.checked = config.options["chk"+opt];
 // text savePasswordCheckboxLabel
 place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
 break;
 case "chk":
 c = document.createElement("input");
 c.setAttribute("type","checkbox");
 c.onclick = this.onChangeOption;
 c.setAttribute("option",opt);
 place.appendChild(c);
 c.checked = config.options[opt];
 break;
 }
};
//}}}
/***
!! Option cookie stuff
***/
//{{{
window.loadOptionsCookie_orig_PasswordTweak = window.loadOptionsCookie;
window.loadOptionsCookie = function()
{
 var cookies = document.cookie.split(";");
 for(var c=0; c<cookies.length; c++) {
 var p = cookies[c].indexOf("=");
 if(p != -1) {
 var name = cookies[c].substr(0,p).trim();
 var value = cookies[c].substr(p+1).trim();
 switch(name.substr(0,3)) {
 case "txt":
 config.options[name] = unescape(value);
 break;
 case "pas":
 config.options[name] = unescape(value);
 break;
 case "chk":
 config.options[name] = value == "true";
 break;
 }
 }
 }
};

window.saveOptionCookie_orig_PasswordTweak = window.saveOptionCookie;
window.saveOptionCookie = function(name)
{
 var c = name + "=";
 switch(name.substr(0,3)) {
 case "txt":
 c += escape(config.options[name].toString());
 break;
 case "chk":
 c += config.options[name] ? "true" : "false";
 // is there an option link with this chk ?
 if (config.options[name.substr(3)]) {
 saveOptionCookie(name.substr(3));
 }
 break;
 case "pas":
 if (config.options["chk"+name]) {
 c += escape(config.options[name].toString());
 } else {
 c += "";
 }
 break;
 }
 c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";
 document.cookie = c;
};
//}}}
/***
!! Initializations
***/
//{{{
// define config.options.pasPassword
if (!config.options.pasPassword) {
 config.options.pasPassword = 'defaultPassword';
 window.saveOptionCookie('pasPassword');
}
// since loadCookies is first called befor password definition
// we need to reload cookies
window.loadOptionsCookie();
//}}}
////===

////+++!![config.macros.upload]

//{{{
config.macros.upload = {
 accessKey: "U",
 formName: "UploadPlugin",
 contentType: "text/html;charset=UTF-8",
 defaultStoreScript: "store.php"
};

// only this two configs need to be translated
config.macros.upload.messages = {
 aboutToUpload: "About to upload TiddlyWiki to %0",
 errorDownloading: "Error downloading",
 errorUploadingContent: "Error uploading content",
 fileNotFound: "file to upload not found",
 fileNotUploaded: "File %0 NOT uploaded",
 mainFileUploaded: "Main TiddlyWiki file uploaded to %0",
 urlParamMissing: "url param missing",
 rssFileNotUploaded: "RssFile %0 NOT uploaded",
 rssFileUploaded: "Rss File uploaded to %0"
};

config.macros.upload.label = {
 promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
 promptParamMacro: "Save and Upload this TiddlyWiki in %0",
 saveLabel: "save to web", 
 saveToDisk: "save to disk",
 uploadLabel: "upload" 
};

config.macros.upload.handler = function(place,macroName,params){
 // parameters initialization
 var storeUrl = params[0];
 var toFilename = params[1];
 var backupDir = params[2];
 var uploadDir = params[3];
 var username = params[4];
 var password; // for security reason no password as macro parameter
 var label;
 if (document.location.toString().substr(0,4) == "http")
 label = this.label.saveLabel;
 else
 label = this.label.uploadLabel;
 var prompt;
 if (storeUrl) {
 prompt = this.label.promptParamMacro.toString().format([this.dirname(storeUrl)]);
 }
 else {
 prompt = this.label.promptOption;
 }
 createTiddlyButton(place, label, prompt, 
 function () {
 config.macros.upload.upload(storeUrl, toFilename, uploadDir, backupDir, username, password); 
 return false;}, 
 null, null, this.accessKey);
};
config.macros.upload.UploadLog = function() {
 return new config.lib.Log('UploadLog', " !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |" );
};
config.macros.upload.UploadLog.prototype = config.lib.Log.prototype;
config.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir, backupDir) {
 var line = " [[" + config.lib.file.basename(storeUrl) + "|" + storeUrl + "]] | ";
 line += uploadDir + " | " + toFilename + " | " + backupDir + " |";
 this.newLine(line);
};
config.macros.upload.UploadLog.prototype.endUpload = function() {
 this.addToLine(" Ok |");
};
config.macros.upload.basename = config.lib.file.basename;
config.macros.upload.dirname = config.lib.file.dirname;
config.macros.upload.upload = function(storeUrl, toFilename, uploadDir, backupDir, username, password)
{
 // parameters initialization
 storeUrl = (storeUrl ? storeUrl : config.options.txtUploadStoreUrl);
 toFilename = (toFilename ? toFilename : config.options.txtUploadFilename);
 if (toFilename === '') {
 toFilename = config.lib.file.basename(document.location.toString());
 }
 backupDir = (backupDir ? backupDir : config.options.txtUploadBackupDir);
 uploadDir = (uploadDir ? uploadDir : config.options.txtUploadDir);
 username = (username ? username : config.options.txtUploadUserName);
 password = config.options.pasUploadPassword; // for security reason no password as macro parameter

 clearMessage();
 // only for forcing the message to display
 if (version.major < 2)
 store.notifyAll();
 if (!storeUrl) {
 alert(config.macros.upload.messages.urlParamMissing);
 return;
 }
 
 var log = new this.UploadLog();
 log.startUpload(storeUrl, toFilename, uploadDir, backupDir);
 if (document.location.toString().substr(0,5) == "file:") {
 saveChanges();
 }
 displayMessage(config.macros.upload.messages.aboutToUpload.format([this.dirname(storeUrl)]), this.dirname(storeUrl));
 this.uploadChanges(storeUrl, toFilename, uploadDir, backupDir, username, password);
 if(config.options.chkGenerateAnRssFeed) {
 //var rssContent = convertUnicodeToUTF8(generateRss());
 var rssContent = generateRss();
 var rssPath = toFilename.substr(0,toFilename.lastIndexOf(".")) + ".xml";
 this.uploadContent(rssContent, storeUrl, rssPath, uploadDir, '', username, password, 
 function (responseText) {
 if (responseText.substring(0,1) != '0') {
 displayMessage(config.macros.upload.messages.rssFileNotUploaded.format([rssPath]));
 }
 else {
 if (uploadDir) {
 rssPath = uploadDir + "/" + config.macros.upload.basename(rssPath);
 } else {
 rssPath = config.macros.upload.basename(rssPath);
 }
 displayMessage(config.macros.upload.messages.rssFileUploaded.format(
 [config.macros.upload.dirname(storeUrl)+"/"+rssPath]), config.macros.upload.dirname(storeUrl)+"/"+rssPath);
 }
 // for debugging store.php uncomment last line
 //DEBUG alert(responseText);
 });
 }
 return;
};

config.macros.upload.uploadChanges = function(storeUrl, toFilename, uploadDir, backupDir, 
 username, password) {
 var original;
 if (document.location.toString().substr(0,4) == "http") {
 original = this.download(storeUrl, toFilename, uploadDir, backupDir, username, password);
 return;
 }
 else {
 // standard way : Local file
 
 original = loadFile(getLocalPath(document.location.toString()));
 if(window.Components) {
 // it's a mozilla browser
 try {
 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
 .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
 converter.charset = "UTF-8";
 original = converter.ConvertToUnicode(original);
 }
 catch(e) {
 }
 }
 }
 //DEBUG alert(original);
 this.uploadChangesFrom(original, storeUrl, toFilename, uploadDir, backupDir, 
 username, password);
};

config.macros.upload.uploadChangesFrom = function(original, storeUrl, toFilename, uploadDir, backupDir, 
 username, password) {
 var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it
 var endSaveArea = '</d' + 'iv>';
 // Locate the storeArea div's
 var posOpeningDiv = original.indexOf(startSaveArea);
 var posClosingDiv = original.lastIndexOf(endSaveArea);
 if((posOpeningDiv == -1) || (posClosingDiv == -1))
 {
 alert(config.messages.invalidFileError.format([document.location.toString()]));
 return;
 }
 var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + 
 store.allTiddlersAsHtml() + "\n\t\t" +
 original.substr(posClosingDiv);
 var newSiteTitle;
 if(version.major < 2){
 newSiteTitle = (getElementText("siteTitle") + " - " + getElementText("siteSubtitle")).htmlEncode();
 } else {
 newSiteTitle = (wikifyPlain ("SiteTitle") + " - " + wikifyPlain ("SiteSubtitle")).htmlEncode();
 }
 revised = revised.replace(new RegExp("<title>[^<]*</title>", "im"),"<title>"+ newSiteTitle +"</title>");
 var response = this.uploadContent(revised, storeUrl, toFilename, uploadDir, backupDir, 
 username, password, function (responseText) {
 if (responseText.substring(0,1) != '0') {
 alert(responseText);
 displayMessage(config.macros.upload.messages.fileNotUploaded.format([getLocalPath(document.location.toString())]));
 }
 else {
 if (uploadDir !== '') {
 toFilename = uploadDir + "/" + config.macros.upload.basename(toFilename);
 } else {
 toFilename = config.macros.upload.basename(toFilename);
 }
 displayMessage(config.macros.upload.messages.mainFileUploaded.format(
 [config.macros.upload.dirname(storeUrl)+"/"+toFilename]), config.macros.upload.dirname(storeUrl)+"/"+toFilename);
 var log = new config.macros.upload.UploadLog();
 log.endUpload();
 store.setDirty(true); store.setDirty(false); // ELS - toggle to ensure notification event after upload
 }
 // for debugging store.php uncomment last line
 //DEBUG alert(responseText);
 }
 );
};

config.macros.upload.uploadContent = function(content, storeUrl, toFilename, uploadDir, backupDir, 
 username, password, callbackFn) {
 var boundary = "---------------------------"+"AaB03x"; 
 var request;
 try {
 request = new XMLHttpRequest();
 } 
 catch (e) { 
 request = new ActiveXObject("Msxml2.XMLHTTP"); 
 }
 if (window.netscape){
 try {
 if (document.location.toString().substr(0,4) != "http") {
 netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');}
 }
 catch (e) { }
 } 
 //DEBUG alert("user["+config.options.txtUploadUserName+"] password[" + config.options.pasUploadPassword + "]");
 // compose headers data
 var sheader = "\r\n";
 sheader += "--" + boundary + "\r\nContent-disposition: form-data;name=\"";
 sheader += config.macros.upload.formName +"\"\r\n\r\n";
 sheader += "backupDir="+backupDir
 +";user=" + username 
 +";password=" + password
 +";uploaddir=" + uploadDir
 + ";;\r\n"; 
 sheader += "\r\n" + "--" + boundary + "\r\n";
 sheader += "Content-disposition: form-data;name=\"userfile\";filename=\""+toFilename+"\"\r\n";
 sheader += "Content-Type: " + config.macros.upload.contentType + "\r\n";
 sheader += "Content-Length: " + content.length + "\r\n\r\n";
 // compose trailer data
 var strailer = new String();
 strailer = "\r\n--" + boundary + "--\r\n";
 var data;
 data = sheader + content + strailer;
 //request.open("POST", storeUrl, true, username, password);
 request.open("POST", storeUrl, true);
 request.onreadystatechange = function () {
 if (request.readyState == 4) {
 if (request.status == 200)
 callbackFn(request.responseText);
 else
 alert(config.macros.upload.messages.errorUploadingContent);
 }
 };
 request.setRequestHeader("Content-Length",data.length);
 request.setRequestHeader("Content-Type","multipart/form-data; boundary="+boundary);
 request.send(data); 
};


config.macros.upload.download = function(uploadUrl, uploadToFilename, uploadDir, uploadBackupDir, 
 username, password) {
 var request;
 try {
 request = new XMLHttpRequest();
 } 
 catch (e) { 
 request = new ActiveXObject("Msxml2.XMLHTTP"); 
 }
 try {
 if (uploadUrl.substr(0,4) == "http") {
 netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
 }
 else {
 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 }
 } catch (e) { }
 //request.open("GET", document.location.toString(), true, username, password);
 request.open("GET", document.location.toString(), true);
 request.onreadystatechange = function () {
 if (request.readyState == 4) {
 if(request.status == 200) {
 config.macros.upload.uploadChangesFrom(request.responseText, uploadUrl, 
 uploadToFilename, uploadDir, uploadBackupDir, username, password);
 }
 else
 alert(config.macros.upload.messages.errorDownloading.format(
 [document.location.toString()]));
 }
 };
 request.send(null);
};

//}}}
////===

////+++!![Initializations]

//{{{
config.lib.options.init('txtUploadStoreUrl','store.php');
config.lib.options.init('txtUploadFilename','');
config.lib.options.init('txtUploadDir','');
config.lib.options.init('txtUploadBackupDir','');
config.lib.options.init('txtUploadUserName',config.options.txtUserName);
config.lib.options.init('pasUploadPassword','');
config.shadowTiddlers.UploadPluginDoc = "[[Full Documentation|http://tiddlywiki.bidix.info/l#UploadPluginDoc ]]\n"; 


//}}}
////===

////+++!![Core Hijacking]

//{{{
config.macros.saveChanges.label_orig_UploadPlugin = config.macros.saveChanges.label;
config.macros.saveChanges.label = config.macros.upload.label.saveToDisk;
//}}}
////===
/***
|''Name:''|UploadPlugin|
|''Type:''|Plugin|
|''Version:''|3.3.1 (30/03/2006)|
|''Source:''|[[TiddlyWiki.BidiX.info/#UploadPlugin|http://tiddlywiki.BidiX.info/#UploadPlugin]]|
|''Documentation:''|[[TiddlyWiki.BidiX.info/#UploadPluginDoc|http://tiddlywiki.BidiX.info/#UploadPluginDoc]]|
|''Author:''|BidiX[at]BidiX.info |
|''Required:''| TW 2.0.6 or better, PHP 4.4 (perhaps less  but not working on 4.1.2) |

!Description
UploadPlugin, with [[store.php]], provides @@upload@@ and @@save to web@@ functions. See HowToUpload ([[HowToUpload|http://TiddlyWiki.bidix.info/#HowToUpload]]).
UploadPlugin uses Username and Password from UploadOptions stored in cookies to authenticate itself to [[store.php]].
French translation available as a separate tiddler UploadPluginMsgFR

!!UploadPlugin
*If the TiddlyWiki is viewed from @@local disk@@ :
**{{{<<saveChanges>>}}} 
***display as ''save to disk''
***work as usual
**{{{<<upload>>}}}
***display as ''upload''
***after saving to disk, upload in the storeUrl directory.
*If the TiddlyWiki is viewed from @@website@@ and is @@readOnly@@ (in core TiddlyWiki since 2.0.6) :
**{{{<<saveChanges>>}}} 
***print nothing
***has been disabled
**{{{<<upload>>}}}
***display as '''save to web''
***save in the uploadDir directory.
*If GenerateAnRssFeed in AdvancedOptions is set :
**generate the content of the RSSFeed 
**upload the RssFile in uploadDir directory
**Caution : use the SiteUrl tiddler to specify the right url of the TiddlyWiki in the generated RssFile
*DisplayMessage
*Log upload action in UploadLog
hint : if UploadLog is the first tiddler in the Timeline Tab, no tiddler has been updated since last upload.

!![[store.php]]
*UserVariables to set :
//{{{
$AUTHENTICATE_USER = true; // true | false
$USERS = array(
 'UserName1'=>'Password1', 
 'UserName2'=>'Password2', 
 'UserName3'=>'Password3'); // set usernames and strong passwords
$DEBUG = false; // true | false
//}}}
*method GET
**display an information page
*method POST
**if $~AUTHENTICATE_USER is ''true''
***presence and value of user and password are checked with $USER and $PASSWORD 
**if toFilename already exists and backDir parameter specified
***rename toFilename to backupDir/toFilename.AAAAMMDD.HHSS.html
**copy temporaryUploadedFile to toFilename
** return status

!Usage : 
{{{
<<upload>>
 uses UploadOptions saved in cookies :
 txtUploadUserName: username
 pasUploadPassword : password
 txtUploadStoreUrl : store script
 txtUploadDir : relative path for upload directory
 txtUploadFilename : upload filename
 txtUploadBackupDir : relative path for backup directory

<<upload [storeUrl [toFilename [backupDir [uploadDir [username]]]]]>>
 optional positional parameters can be passed to overwrite UploadOptions in this order. 
}}}

Install the {{{<<upload ... >>}}} macro in SideBarOptions just below {{{<<saveChanges>>}}} macro.


!User manual
See HowToUpload

!Installation :
*Install the UploadPlugin as usual
*Upload the [[store.php]] file on your php aware webserver in your TiddlyWiki directory
*Protect your server against malicious upload. Two approaches :
**set $~AUTHENTICATE_USER to true in the [[store.php]] script
***configure $USER and $PASSWORD in the [[store.php]] script on your webserver
***set UploadOptions in conformity with [[store.php]]
**Use server protection :
***for Apache web server ([[for detail see Apache documentation|http://httpd.apache.org/docs/1.3/howto/htaccess.html]]) : 
****configure and upload the [[.htaccess]] [[.passwd]]
***for other web servers see the appropriate documentation
*Configure an upload button, for example in the SideBarOptions
!Suppported Browser
*Firefox : tested Ok
*Internet Explorer : tested Ok
*Safari : reported ok on OS X
*Others : Not tested, please report status.

!Revisions
*V 3.3.1 (30/03/2006)
**bug in backup folder when uploading rssfile fixed
*V 3.3.0 (12/03/2006)
**Code refactoring
**suppress saveChanges hijacking
*V3.2.2 (25/02/2006)
**Use PasswordTweak 1.0.1
**uploaddir is a relative path
**backupdir is a relative path
+++[previous revisions]
*V3.2.1 (13/02/2006)
**name and password added to open.request (Thanks to TedPavlic)
*V3.2.0 (14/02/2006)
**Use PassworDTweak (http://tiddlyWiki.bidix.info/#PasswordTweak) for password
*V3.1.0 (12/02/2006)
**UploadOptions in Cookies
**Username and password from UploadOptions pass to store.php script for authentification check
*V3.0.3 (03/02/2006)
**Firefox 1.5.0.1 crashes due to global var fixed
*V3.0.2 (25-Jan-2006)
**HTTPS compatible
*V3.0.1 (18-Jan-2006)
**UTF8toUnicode conversion problem in Firefox
*V3.0.0 (15-Jan-2006)
**Asynchronous upload
**Synchronous upload before unload of the page
**All strings extracted in macro config
**Compatibility checked with TW 2.0.2 & TW 1.2.39 for both FF 1.5 and IE 6
*V2.0.2 (8-Jan-2006)
**conversion of SiteTitle and SiteSubtitle in web page Title
*V2.0.1 (8-Jan-2006)
**Compatibilty with TiddlyWiki 2.0.1
*V2.0.0 (3-Jan-2006)
**Save to web
**Compatibilty with TiddlyWiki 1.2.39 and TiddlyWiki 2.0.0 Beta 6
*v1.1.0 (27-Dec-2005)
**Upload RSS File
*v1.0.3 (26-Dec-2005)
**UploadLog tiddler
*v1.0.2 (24-Dec-2005)
**Optional parameter toFilename
**Optional parameter backupDir
*v1.0.1 (23-Dec-2005)
**reformatting code
* v1.0.0 (17-Dec-2005)
** first public working version
===

// null logger : no more UploadLog and no upload logging
// BidiX - 2006/11/8
//{{{
config.macros.upload.UploadLog = function() {return this;};
config.macros.upload.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {};
config.macros.upload.UploadLog.prototype.endUpload = function() {};
//}}}
The name //Emory Cottage// came from the designer who drew up the final plans.  I've spent part of the summer for the last 30 years in a place where houses had names instead of street numbers, so a name for a house was very natural to me.  The designer suggested "Brown Manor" and that did not seem right.  Truly, there are manors in Druid Hills, but my house is not one of them.  So, we settled on //Emory Cottage,//

(Sadly, while the houses on Pawley's Island still have names, the new-fangled innovation of street numbers was introduced about the turn of the 21st Century.)