How to get selected node

Here’s a two-parter question:

First, I’d like to get the selected node and am not sure how. I know (from the example script in the SDK) how to get the selected text, but I can’t change from “selectedText” to “selectedRange” to get the node:

tell front document of application "FoldingText"
evaluate script "
	function(editor, options) {
		return editor.selectedRange();
	}"
end tell

That returns: FoldingText got an error: AppleEvent handler failed.

What should I be doing differently? Where in the SDK should I have seen this?

Second, I’m just getting my feet wet with scripting FT. I have a functional beginner understanding of Javascript, but am having a lot of trouble with the SDK, as you can see. The question above is, I realize, quite basic. The beginner info I’ve leared about Javascript (mostly a few Lynda courses) appears to have little overlap with the kind of stuff in the SDK. Do I need to study something else? What am I doing wrong?

Thanks!

Hi,

You need to add “.textInRange()” to get the actual text. In your code, you are returning a Range object, not text. When the scripting bridge from JavaScript to AppleScript tries to translate it, it can’t. You code should be:

tell front document of application "FoldingText"
    evaluate script "
    function(editor, options) {
        return editor.selectedRange().textInRange();
    }"
end tell

And then it will work. You can check out all the examples in my FoldingText Alfred Workflow (http://www.packal.org/workflow/folding-text-workflow) and a Tutorial I wrote: Customizing FoldingText. I have another tutorial coming that uses JavaScript for Automation.

I think it can help a lot to:

  1. Fire up the SDK version of the editor and paste some text in it,
  2. change evaluate to debug in your calling script,
  3. add a debugger; statement to your called script,
  4. then run and step through, watching the variables change and inspecting their structure.
function run() {

	function fnFT(ed, opt) {
		var lstNodes = ed.selectedRange().nodesInRange(),
			oNode = lstNodes.length ? lstNodes[0] : null;

		debugger;

		return oNode ? oNode.text() : '';
	}

	var docsFT = Application("FoldingText").documents(),
		varResult = docsFT.length && docsFT[0].debug({
			script: fnFT.toString(),
			withOptions: {}
		});

	return varResult;
}

PS if you haven’t had a chance to look at Douglas Crockford’s ‘The Good Parts’, then I do recommend it - it’s well written, very helpful, and a lot of the code that you read will have been written by people who have read it.

The other thing I find very helpful is to use a linter like JSLint or JSHint.

Have fun !

Hi @raguay, thanks sincerely for your advice! I reread your tutorial and am eagerly awaiting the next installment.

@complexpoint Thanks very much for the tips—I will give these things a go. Much obliged as always.

Hi @jackbrannen,

When you look in the SDK for different functions, it directly tells what it returns. For example:

This is the Editor description in the SDK. You see the selectedRange() function has the ‘->’ that shows it is returing a Range object. You then lookup Range and find a function that returns what you need. The description of the function is somewhat ambiguous. It just says that it returns the selected range without saying how it returns it. But, by looking at the function description above, the return type is always after the ‘->’ sign.

I hope this helps!

Thanks again, @raguay. This makes sense and I have successfully made a few scripts. I’m also still learning Javascript, so it’s slow going, but things are unlocking for me.

Hope to have something useful to share on the forums someday…

I am glad it was helpful. Looking forward to seeing what you create. Have fun coding!