Error when setting Text.fontFamily

Getting an error when setting the font family property on a Text node.

console.log("Font name:" + sceneNode.fontFamily); // Font name: Athelas
sceneNode.fontFamily = "Arial";

Gives this error:

 Error: invalid font family
    at setProperty (lib/scenegraph/TextExtension.js:1:2486)
    at Text.set (lib/scenegraph/TextExtension.js:1:2818)
    at Text.<anonymous> (plugins/ScenegraphWrappers.js:1:23385)
    at Text.<anonymous> (plugins/ScenegraphWrappers.js:1:2423)
    at changeTextFont (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:248:29)
    at walkDownTree (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:263:2)
    at walkDownTree (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:271:13)
    at fontInputChangeHandler (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:210:9)
    at fontInputKeypressHandler (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:217:3)
    at b.onkeydown (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:108:36)
    at b.g (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:274:271)
    at uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:853
    at j (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:745)
    at f (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:350)
    at e (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:152)
    at i (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:1057)
    at dispatchNativeEvent (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:2075)
    at b.value (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/to

Update:
It works when I set a single item but it creates an error when I’m walking down the artboard or group.

Do you mean applying it to multiple Text nodes at once? I’ve tried, it works even for more than one element.
Still getting the invalid font family error?

Here’s what I’m using:

function fontInputChangeHandler() {
    var value = model.fontInput.value;
	var element = model.selection.items.length ? model.selection.items[0] : null;

	if (element) {
	    walkDownTree(element, changeTextFont, value);
	}
}

function fontInputKeypressHandler(event) {

	if (event.keyCode==13) {
		fontInputChangeHandler();
	}
}

/**
 * Change the font of the scene node
 * @param {SceneNode} node
 * @param {Array} args
 **/
function changeTextFont(node, args) {
    var fontName = args[0];

    if (node instanceof Text) {
        log("Text: " + node.name);
        log("Text font: " + node.fontFamily);
        log("Set to font: " + fontName);
        try {
            node.fontFamily = fontName;
        }
        catch (error) {
            log(error.stack);
        }
    }
}

/**
 * Calls the passed in function on the node and it's descendants 
 * @param {SceneNode} node 
 * @param {Function} command 
 **/
function walkDownTree(node, command, ...args) {

	command(node, args);

	if (node.isContainer) {
		var childNodes = node.children;

		for(var i=0;i<childNodes.length;i++) {
			let childNode = childNodes.at(i);
			walkDownTree(childNode, command, args);
		}
	}
}

Edit:
I think I see an error. Passing in the args each call to a rest array may be making an array of array.

Edit 2:
I’ve changed it to pass in a normal single argument

/**
 * Calls the passed in function on the node and it's descendants 
 * @param {SceneNode} node 
 * @param {Function} command 
 **/
function walkDownTree(node, command, value) {
    command(node, value);

    if (node.isContainer) {
        var childNodes = node.children;

        for(var i=0;i<childNodes.length;i++) {
            let childNode = childNodes.at(i);

            walkDownTree(childNode, command, value);
        }
    }
}

/**
 * Change the font of the scene node
 * @param {SceneNode} node
 * @param {String} value
 **/
function changeTextFont(node, fontName) {

    if (node instanceof Text) {
        log("Text: " + node.name);
        log("Text font: " + node.fontFamily);
        log("Set to font: " + fontName);

        try {
            node.fontFamily = fontName;
        }
        catch (error) {
            log(error.stack);
        }
    }
}

but now I’m getting another error:

Plugin Error: Plugin made a change outside the current edit context
    at convertPluginErrorToString (plugins/PluginErrorUtil.js:1:198)
    at internalFormatPluginError (plugins/PluginErrorUtil.js:1:503)
    at internalReportPluginError (plugins/PluginErrorUtil.js:1:610)
    at Object.reportPluginError (plugins/PluginErrorUtil.js:1:1042)
    at r (plugins/ScenegraphGuard.js:1:310)
    at Object.checkChange (plugins/ScenegraphGuard.js:1:810)
    at Object.EventEmitter._emitEvent (third_party/events.js:1:1178)
    at Object.EventEmitter.emit (third_party/events.js:1:1668)
    at Text.Group.notifyChanged (lib/scenegraph/GroupExtension.js:1:879)
    at setProperty (lib/scenegraph/TextExtension.js:1:2486)
    at Text.set (lib/scenegraph/TextExtension.js:1:2818)
    at Text.<anonymous> (plugins/ScenegraphWrappers.js:1:23385)
    at Text.<anonymous> (plugins/ScenegraphWrappers.js:1:2423)
    at changeTextFont (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:241:29)
    at walkDownTree (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:255:5)
    at walkDownTree (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:263:13)
    at fontInputChangeHandler (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:216:9)
    at fontInputKeypressHandler (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:223:3)
    at b.onkeydown (/Users/user/Library/Application Support/Adobe/Adobe XD CC/develop/typeswitcher/main.js:113:36)
    at b.g (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:274:271)
    at uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:853
    at j (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:745)
    at f (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:350)
    at e (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:152)
    at i (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:1057)
    at dispatchNativeEvent (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:262:2075)
    at b.value (uxp://uxp-internal/home/ubuntu/jenkins/workspace/Torq/torq-native/release-2.2.0/build/modules_gen/domjs/src/js/domjs_scripts.js:238:6926)

Sorry, I can’t replicate your logic at this moment.
My quick test was simply:

for(let i = 0; i < selection.items.length; i++)
{
    	let sceneNode = selection.items[i];
    	console.log("Font name:" + sceneNode.fontFamily);
    	sceneNode.fontFamily = "Arial";
}

Looking at your last error it seems you are trying to access something inside a different container.

Correct. It works when in the same context but the error is thrown when applying to other contexts.
But I have been misunderstanding the edit context. I thought that you can edit anything in the current group and groups it owns but it appears that’s not possible?

However it sort of still works:

But it doesn’t save the changes when the dialog closes.

So I’m going to add a feature request and link it back here.

@Velara edit context covers the current selection and its immediate children. If one of the current selection children has a child, the second level child will be out of the edit context.

Any changes will be cancelled if the dialog promise is not resolved. In the GIF you posted above, it looks like there was an error while user interacts with the plugin in the dialog. In that case, promise is not fulfilled and any changed made will be rolled back.

I do see that you have posted a feature request for this though!

2 Likes

For what it’s worth, the original error you were hitting wasn’t related to edit contexts. The “invalid font family” message would only happen if you try to set fontFamily to something other than a string.

Sounds like you fixed that in your “Edit 2” above, though.

1 Like

Side Question: how did you add that alert dialog? Where you input the font label

What do you mean? Here’s an example plugin that shows how I’m calling an alert, https://github.com/velara3/xd-examples/tree/master/statistics.

Note: Due to new changes to plugins any size or position values you use should have the length added to it going forward. So where I have code that says fontSize: 10 it should be fontSize: "10px" and any styles should be inside the styles object.

Some of the code is inspired by the great Adobe plugin examples here.

2 Likes

I mean how do you show a basic alert? I’m unable make on so far.

Something like this will do the trick:

    var dialog = document.createElement("dialog");
    dialog.innerHTML = `
        <form method="dialog">
            <h1>Title</h1>
            <hr>
            <div>Alert message goes here...</div>
            <footer>
                <button id="ok" type="submit" uxp-variant="cta">OK</button>
            </footer>
        </form>`;
    document.appendChild(dialog);

    return dialog.showModal().then(function () {
        dialog.remove();
    });

There are also various open-source helper libraries you can use for this if you don’t need much control of the dialog’s appearance/contents and you want to have simpler code. Here’s one example: https://github.com/AdobeXD/plugin-samples/blob/master/ui-dialog-variations/lib/dialogs.js#L256-L265.