Replacing the Linktype of a link between notes with action code in a stamp?

I am trying to replace the linkType of several notes with another linkType. How would I do that with a stamp?
Let’s say I have the link between note1 and note2 , note1 and note3 is untitled
I would like to change the linkType to “IsPartOf” with action code in a stamp to multiple notes. Certainly this is easily done manually, but the question is, how do I do this with multiple notes in a stamp. I am thinking I can select all the destination notes and do some magic code to the incoming links.
This I am sure is simple but I have never done this before with action code, always manually.

I am not sure how to do this with code?

Thanks
Tom

The backstage release (and the upcoming 9.6 release) make this much easier. So a brief wait makes sense, if possible.

1 Like

Tom, this will do the trick (supported in in 9.5):

eachLink(x){
   if(x["type"]=="*untitled"){
      x["type"]="IsPartOf";
   };
};

Remember, link type names are case-sensitive and directional.

TBX L - Modify Link Type Names.tbx (142.7 KB)

2 Likes

In case anyone wonders, in v9.5.2—i.e. in the post above, a link’s type is editable via eachLink(). Plus, as @eastgate notes, real soon now even more aspects of a link with be editable in action code using eachLink().

I wrote some handlers for myself to deal with links - it is work in progress and it seems I will have to make some adjustments for the upcoming version of TBX - anyhow, just a playground for you:

// Link management
function changeTheLinks_db(theParamters:dictionary) {
	// Parameters passed as a dictionary with type:value pairs
	// changeAllLinks_db("target:/dummy;task:changeType;old:agree;new:disagree");
	// changeAllLinks_db("target:dummy2;task:removeType;dir:out;typ:clarify");
	// changeAllLinks_db("target:all;task:removeType;dir:out;typ:clarify");
	// changeAllLinks_db("target:dummy2;task:addLink;typ:test;tonotes:[dummy;dummy3]");

	if(!theParameters.empty){
		var:string theTarget = theParamters["target"];
		var:string theTask   = theParamters["task"];

		if(theTask == "changeType"){
			var:string theOld = theParamters["old"];
			var:string theNew = theParamters["new"];
			if((theOld != "") & (theNew != "")){
				eachLink(aLink, theTarget){
					if(aLink["type"] == theOld){
						aLink["type"] = theNew;
					};
				};
			};
		};

		if(theTask == "removeType"){
			var:string theDirection = theParamters["dir"];
			var:string theType      = theParamters["typ"];

			if(theDirection == "out"){
				eval(theTarget,"unlinkTo(all,'" + theType + "')" );
			} else {
				eval(theTarget,"unlinkFrom(all,'" + theType + "')" );
			};
		};

		if(theTask == "addLink"){
			var:string theType    = theParamters["typ"].trim();
			var:list relatedNotes = theParamters["tonotes"].replace("(\[|\])",""); ;

			if(relatedNotes.count > 0) {
				relatedNotes.each(relatedNote){
					createLink(theTarget,relatedNote,theType);
				};
			};
		};
	};
};

// remove all links on all children of a note that have a specific type
// removeAllLinks_db("target:/Test/;typ:agree;dir:out;");
function removeAllLinks_db(theParamters:dictionary){
	if(!theParameters.empty){
		var:string startNode    = theParamters["target"];
		var:string theType      = theParamters["typ"];
		var:string theDirection = theParamters["dir"];
		var:list allMyNotes     = collect(children(startNode),$IDString);
		var:string theParas     = "";

		if(!allMyNotes.empty){
			allMyNotes.each(singleNote){
				theParas = "target:" + $Path(singleNote) + ";task:removeType;dir:" + theDirection + ";typ:" + theType;
				changeTheLinks_db(theParas);
			};
		};
	};
};

There are only two functions for the link management: changeAllLinks_db() and removeAllLinks_db(). The first one offers different options - use the attribute “task” to define one of those like:

changeAllLinks_db("target:/dummy;task:changeType;old:agree;new:disagree");

Will change all links of the note “/dummy” with the type “agree” to the type “disagree”

changeAllLinks_db("target:dummy2;task:removeType;dir:out;typ:clarify");

Will remove all outbound links of the type “clarify” from the note “dummy2”;

changeAllLinks_db(target:all;task:removeType;dir:out;typ:clarify);

Will remove all links with the type “clarify” from the current note.

changeAllLinks_db(target:dummy2;task:addLink;typ:test;tonotes:[dummy;dummy3]);

Will add a link from note “dummy2” to the notes “dummy” and “dummy3”

and with removeAllLinks_db(“target:/Test/;typ:agree;dir:out;”); the outbound links of all children of note “/Test/” and the type “agree” will be removed.

This is work in progress and will be improved if the new version is out - have fun!

2 Likes

Hi Detlef,
Thanks for the magical code. Two quick questions:

  1. Should this be changed in the code?

  2. Is this line needed?

Based on MarkB’s comment, here: Define "current note" with action code - #3 by eastgate

Many thanks
Tom

(1) maybe yes - you can change any number of links depending on the note you selected (“target:a note to start”)
(2) yes! I don’t want to run any code if the needed input is not there. And for the 2nd example: even if each() will do nothing if the list passed is empty, I still like to test for an empty list. I do forget this sometimes, but normally I do it that way. Sometimes you can run into an exception and sometimes the code is more robust - it’s trained to do it always :wink: Maybe at some point I would like to react if an empty list has been passed…

1 Like