Script Works on iPhone but not on iMac

When establishing a group of drafts that are linked to each other with titles, it is important that you be able to change a title (e.g., to clarify it) without breaking all the links. I’m therefore trying to create an action that (1) changes a title, and (2) looks through the current workspace to find and update any links associated with the old title.

Being a rookie at JavaScript, I’ve borrowed heavily from scripts written by others. The logic is:

a. Prompt for the new title.
b. Create variables for the old and new titles and the old and new links.
c. Change the title.
d. Search through the current workspace and update the links.

The action works reliably when executed from my iPhone. When executed from my iMac, the links are changed, but the title is not. I would appreciate help in figuring out what I am doing wrong.

//This script prompts for a new title and then replaces the old title with the new title.//
//The script also searches the current workspace to locate links based on the old title, and updates them.//

// prompt for new title.//
let p = Prompt.create();
p.title = “New Title”;
p.message = “Enter the new title. The old title and all links using that title will be replaced by the new title.”;

p.addTextField(“newTitle”, “New Title”, “”, {
“placeholder”: " ",
“autocorrect”: false,
“autocapitalization”: “none”,
“wantsFocus”: true
});

p.addButton(“Replace”);

if (p.show()) {
//Establish variables for the old and new titles and the old and new links.//
let oldTitle = draft.displayTitle;
let oldLink = [[${oldTitle}]];
let newTitle = p.fieldValues[“newTitle”];
let newLink = [[${newTitle}]];

//Update the title of the draft.//
draft.content = draft.content.replaceAll(oldTitle, newTitle);	draft.update();

//Search the current workspace looking for links based on the old title and update them.//
let count = 0
var drafts = app.currentWorkspace.query("all");
	for (let d of drafts) {
		d.content = d.content.replaceAll(oldLink, newLink);
		d.update();
		count++
			}
	alert(count + "drafts evaluated.");
}

The easiest way to share action content when asking for help is to share the action to the action directory (in action edit screen) as “unlisted” and post the link here. Then people can install the action to look at it. I tried pasting this script in, but am getting compile errors.

My guess, looking at this is that you are creating a race condition updating the draft currently in the editor, however, which might come out a little different on different platforms. Presumably the current draft is also in the workspace you are looping over, so you are updating it twice.

If you move the update of the current draft after the loop, you could avoid this, but also you could prevent updating the current draft in the loop, since it should not be needed, like:

for (let d of drafts) {
    if (d.uuid != draft.uuid) {
        d.content = d.content.replaceAll(oldLink, newLink);
        d.update();
        count++
    }
}

Thanks for the information on how to share a link to an Action.

https://actions.getdrafts.com/a/10r

I tried both of your suggestions and couldn’t get either to work. The current draft is in the workspace I am looping over.

Definitely some tricky timing issues that explain the differences in behavior. I will look into those, but for the time being, it’s easy to workaround by modifying the text directly in the editor for the current draft.

Try this modified version.

The version you sent changes the title, but not the links in other drafts that need to be updated. That problem exists on both macOS and iOS.

The //d.update() in the loop is commented out, sorry. Did not want to actually make those changes in my test data. You should be able to make that change and it’ll be fine.

Thanks, didn’t notice that. Works great and I appreciate the help.

I am experiencing a similar error as @Bjb - in that both the original action: Title and Links and the updated action Title and Links?? is throwing an error - removed “//” from: .d.update() - on Mac OSX but works on iOS.

The error:

Script Error: TypeError: d.content.replaceAll is not a function. (In ‘d.content.replaceAll(oldLink, newLink)’, ‘d.content.replaceAll’ is undefined)
Line number: 32, Column 45

Any ideas on a solution?

What version of macOS? replaceAll is a relatively recent addition to JS language support.

10.13.6 and 10.14.6 > Second time I’ve encountered errors due to age of the OSX - A sign the sun is setting… Thanks for clarifying and putting questions to rest.

If you add a script step set to be enabled on Mac only to the top of the action, with the below, it will start working:

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

It implements the replaceAll method for the JavaScript version that does not support it.

2 Likes

This worked - thank you so much!

“ 10.13.6 and 10.14.6".

Not particularly to pick on you but do we know if Catalina or Big Sue support replaceAll() ?

Yes. Catalina and greater has it.

Honestly, I’ve looked a couple of times and never found a very clear explanation of JavaScriptCore versions on macOS. I’m not entirely clear if it’s updated exclusively with Safari updates, or if Safari bundles it’s own separate framework version.

It’s pretty clear cut on iOS, since Safari is bundled with the OS.

1 Like