Name:FamilyTreeUtilsPlugin
Description:Adds useful macros for the purpose of family tree related fun
Version:0.3.12
Date:July 2010
Source:http://familytree.tiddlyspace.com
Author:Jon Robson
License:BSD open source license
CoreVersion:2.3

Notes

Updates newTiddler macro
Updates saveTiddler to update other tiddlers when a spouse is added / a mother/father renamed
updates date view type to show years when the rest of the string is 0s
additional bracketedlist and year view type
listChildren, tiddlerGender, age and familytreelist macros
macro
(function($) {
if(!config.macros.showInstall) {
config.macros.showInstall = {handler:function(){}};
}
merge(config.shadowTiddlers, { excludeTreeViewTemplate : "", systemConfigViewTemplate: "",
ListOfWomen: "", ListOfMen: "", ListOfPlaces: "", placeViewTemplate: "", sexDefinition: ""});

var _date = config.macros.view.views.date;
config.macros.view.views.date = function(value,place,params,wikifier,paramString,tiddler) {
	var isString = typeof(value) == "string";
	if(isString && value.substr(4, 4) == "0000") { // only year
		config.macros.view.views.year.apply(this, arguments);
	} else if(isString && value.substr(6, 4) == "0000") { // only month and year
		var year = value.substr(0, 4);
		var month = config.messages.dates.shortMonths[parseInt(value.substr(4, 2), 10) - 1];
		$("<span />").addClass("year").text("%0 %1".format([month, year])).appendTo(place);
	} else {
		_date.apply(this, arguments);
	}
};

config.macros.view.views.year = function(value,place,params,wikifier,paramString,tiddler) {
	var year = value.substr(0,4);
	$("<span />").addClass("year").text(year).appendTo(place);
};

config.macros.view.views.bracketedlist = function(value, place, params, wikifier, paramString, tiddler) {
	var links = value.readBracketedList();
	for(var i = 0; i < links.length; i++){
		config.macros.view.views.link(links[i], place, params, wikifier, paramString, tiddler);
		$("<span />").html("&nbsp;").appendTo(place);
	}
};


var _saveTiddler = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
	var tiddler, titleThis, newTitleThis;
	if(title instanceof Tiddler) {
		tiddler = $.extend(new Tiddler(title.title), title);
		titleThis = title.title;
		newTitleThis = newTitle;
	} else {
		tiddler = new Tiddler(newTitle);
		tiddler.fields = fields;
		tiddler.tags = tags;
		titleThis = title;
		newTitleThis = newTitle;
	}
	if(!newTitle) {
		newTitleThis = titleThis;
	}
	var changed = [];
	var changedTitle = newTitleThis != titleThis;
	var spousesToUpdate = [];
	if(tiddler.fields && tiddler.fields.spouses) {
		spousesToUpdate = tiddler.fields.spouses.readBracketedList();
	}
	if(changedTitle){
		var tiddlers = store.getTiddlers();
		for(var i = 0; i < tiddlers.length; i++) {
			var tid = tiddlers[i];
			var changedTiddler = false;
			if(spousesToUpdate.indexOf(tid.title) != -1) { // make sure the other tiddler knows they have a spouse
				var theirSpouses = tid.fields.spouses ? tid.fields.spouses.readBracketedList() : [];
				theirSpouses.pushUnique(newTitleThis);
				tid.fields.spouses = String.encodeTiddlyLinkList(spouseList);
				changedTiddler = true;
			}

			if(changedTitle) { // update other tiddlers in case of changed name
				if(tid.fields.mother == titleThis){
					tid.fields.mother = newTitleThis;
					changedTiddler = true;
				}
				if(tid.fields.father == titleThis){
					tid.fields.father = newTitleThis;
					changedTiddler = true;
				}
				if(tid.fields.spouse) {
					var spouseList = tid.fields.spouse.readBracketedList();
					var update = spouseList.indexOf(titleThis);
					if(update != -1) {
						spouseList[update] = newTitleThis;
						tid.fields.spouse = String.encodeTiddlyLinkList(spouseList);
						changedTiddler = true;
					}
				}
			}

			if(changedTiddler) {
				tid = _saveTiddler.apply(this, [tid]);
				changed.push(tid)
			}
		}
		autoSaveChanges(null, changed);
	}
	return _saveTiddler.apply(this, arguments);
};
config.macros.age ={
	handler: function(place, macroName, params, wikifier, paramString, tiddler){
		var d1 = tiddler.fields["dob"];
		var d2 = tiddler.fields["dod"] || new Date().formatString("YYYY0MM0DD000000");
		var y1 = parseInt(d1.substr(0,4));
		var y2 = parseInt(d2.substr(0,4));

		if(y1 == Number.NaN || y2 == Number.NaN || y1== 0 || y2 == 0) {
			return;
		}
		var m1 = parseInt(d1.substr(4,2));
		var m2 = parseInt(d2.substr(4,2));

		var day1 = parseInt(d1.substr(6,2));
		var day2 = parseInt(d2.substr(6,2));

		var ageY = y2 - y1;
		var ageM = m2 - m1;
		if(m2 > m1){
			ageM = m2 - m1;
		} else if(m2 < m1){
			ageM = 12 -(m1- m2);
			ageY -= 1;
		}

		if(ageY != Number.NaN) {
			var ageStr = ageY + " years";
			if(ageM != 0 && ageM != Number.NaN) {
				 ageStr += " and " + ageM + " months";
			}
		}
		$(place).text(ageStr);
	}
};

config.macros.familytreelist = {
	handler: function(place, macroName, params, wikifier, paramString, tiddler){
		var param = paramString.parseParams();
		var sex = getParam(param, "sex");
		var filter = getParam(param, "filter")
		var print = "";
		var tiddlers = !filter ? store.getTiddlers() : store.filterTiddlers(filter);
		var sort = getParam(param,"sort");
		tiddlers = sort ? store.sortTiddlers(tiddlers, sort) : tiddlers;

		for(var i=0; i < tiddlers.length;i++) {
			var tid = tiddlers[i];
			var good = false;
			if(!sex) {
				good = true;
			} else if(tid.fields.sex && tid.fields.sex == sex) {
				good = true;
			}
			if("excludeTree" in tiddler.tags) {
				good = false;
			}
			if(good) {
				print += tid.title+"\n";
			}
		}
		wikify(print, place);
	}
};

var listChildren = config.macros.listchildren = {
	locale: {
		noChildren: "No children"
	},
	handler: function(place, macroName, params, wikifier, paramString, tiddler){
		var parent = tiddler.title;
		var children = [];
		var t = store.getTiddlers();

		for(var i=0; i < t.length; i++){
			var person = t[i];
			if(person.fields.father == parent){
				children.push(person);
			}
			else if(person.fields.mother == parent){
				children.push(person);
			}
		}

		var param = paramString.parseParams();
		var sort = getParam(param, "sort");
		if(sort){
			children = store.sortTiddlers(children, sort);
		}

		if(children.length === 0){
			var div = $("<div />").text(listChildren.locale.noChildren).appendTo(place);
		} else{
			var ul = $("<ul />").appendTo(place);
			for(var i = 0; i < children.length; i++) {
				var child = children[i];
				var name = child.title;
				var dob = child.fields.dob;
				var dod = child.fields.dod;
				dob = dob ? dob.substr(0,4) : "";
				dod = dod ? dod.substr(0,4) : "";
				var lifespan = dob || dod ? " (%0-%1)".format([dob, dod]) : "";
				var child = $("<a />").addClass("child").text(name + lifespan).attr("title", name).click(function(ev){
					story.displayTiddler(ev.target,this.title);
				});
				var li = $("<li />").append(child).appendTo(ul);
			}
		}
	}
};
config.macros.tiddlerGender ={
	handler: function(place, macroName, params, wikifier, paramString, tiddler){
		place = $(place);
		var sex = tiddler.fields.sex;
		if(sex == 'M'){
			place.addClass("sexMale");
		}
		else if(sex == 'F'){
			place.addClass("sexFemale");
		}
	}
};

config.commands.addChild = {
	text: "Add Child",
	tooltip: "add a child",

	handler: function(event, src, title){
		var parent = store.getTiddler(title);
		var parentSex = parent.fields.sex;
		var spouses = parent.fields.spouse || "";
		var spouseList = spouses.readBracketedList();
		var parent2;
		for(var i = 0; i < spouseList.length && !parent2; i++) {
			var s = spouseList[i];
			var answer = confirm("was %0 the other parent?".format([s]));
			if(answer) {
				parent2 = s;
			}
		}
		parent2 = parent2 ? parent2 : "";
		var childName = prompt("What is the name of the child?");
		var custom = "";
		if(parentSex && childName){
			if(parentSex == "F") {
				custom = 'mother:"%0" father:"%1"'.format([title, parent2]);
			} else if(parentSex == "M") {
				custom = 'father:"%0" mother:"%1"'.format([title, parent2]);
			}
			story.displayTiddler(null, childName, DEFAULT_EDIT_TEMPLATE, null, null, custom);
		} else {
			alert("I can't do this without the child name and the sex of this person..");
		}
	}
};

merge(config.macros.newTiddler,{
	label: "new person",
	prompt: "Create a new person in your family tree",
	title: "New Person",
	accessKey: "N"});

config.macros.viewFieldTiddler = {
	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var field = params[0];
		var reference = tiddler[field] || tiddler.fields[field];
		tiddler = reference ? store.getTiddler(reference) : null;
		var newParams = params.slice(1, params.length);
		var newParamString = newParams.join(" ");
		config.macros.view.handler(place,macroName,newParams,wikifier,newParamString,tiddler);
	}
};
}(jQuery))
bag
familytree_public
created
Tue, 06 Jul 2010 15:11:59 GMT
creator
jon
modified
Sat, 05 Feb 2011 13:27:28 GMT
modifier
jon
tags
excludeLists
excludeSearch
systemConfig
mother
Grandma