Sal
December 5, 2021, 3:23pm
#1
I read the developer documentation and created the Hello World example which ran as expected — excellent!
However, when I tried to use the provided URL example code, it failed to work as indicated. Is this a known issue or am I missing something?
<!DOCTYPE html>
<html>
<body>
<a href="" onclick="craft.editorApi.openUrl('http://craft.do'); return false">CRAFT</a>
</body>
</html>
Cheers!
Sal Soghoian
Sal
December 5, 2021, 8:41pm
#2
I also tried using the Hello World code adapted with the openURL command, but it fails as well:
<!DOCTYPE html>
<html>
<body>
<button id="btn-execute">Omni Automation</button>
<script>
const button = document.getElementById("btn-execute")
button.addEventListener("click", async () => {
await craft.editorApi.openUrl('https://omni-automation.com')
})
</script>
</body>
</html>
Sal
December 6, 2021, 1:47am
#3
I tried adapting the Hello World example to use the SpeechSynthesis JavaScript class and it failed as well. Not sure why.
<!DOCTYPE html>
<html>
<body>
<button id="btn-execute">Greet</button>
<script>
const button = document.getElementById("btn-execute")
button.addEventListener("click", async () => {
const utterance = new SpeechSynthesisUtterance("Hello world!");
speechSynthesis.speak(utterance);
})
</script>
</body>
</html>
balint
December 6, 2021, 6:26am
#4
My gut feeling would be that the craft object or speech Synthesis Class aren’t loaded in this case. If you can send over your full code in Zip we can further analyse?
Sal
December 6, 2021, 7:31am
#5
How do I send the zips to you? Can I post here?
Sal
December 6, 2021, 7:35am
#6
Craft-Extensions.zip (139.2 KB)
Thank you! Here are the two examples I posted.
zsombor
December 6, 2021, 4:07pm
#8
Hey, I fixed the documentation.
It should be: with openURL not openUrl:
<a href="" onclick="craft.editorApi.openURL('http://craft.do'); return false">CRAFT</a>
Sal
December 6, 2021, 4:22pm
#9
How about that? Thank you, that works.
Any ideas as to why the Speech classes aren’t part of the loaded JavaScript?
Sal
December 6, 2021, 4:25pm
#10
Here is an example of combining the use of Omni Automation with Craft extensions to create a new task instance in OmniFocus:
<!DOCTYPE html>
<html>
<body>
<button id="btn-execute">Omni Automation</button>
<script>
const button = document.getElementById("btn-execute");
button.addEventListener("click", async () => {
// CREATE/SEND OMNI AUTOMATION SCRIPT URL
// DOCUMENTATION: https://omni-automation.com/script-url/index.html
// FUNCTION TO BE EXECUTED BY OMNIFOCUS
function newOmniFocusTask(taskName){
tsk = new Task(taskName)
URL.fromString(`omnifocus://task/${tsk.id.primaryKey}`).open()
}
// CREATE FUNCTION AND CONTENT STRINGS
contentString = JSON.stringify("My New Task");
encodedContent = encodeURIComponent(contentString);
functionString = newOmniFocusTask.toString();
encodedFunction = encodeURIComponent(functionString);
// CREATE SCRIPT URL
url = 'omnifocus://localhost/omnijs-run?script=' +
'%28' + encodedFunction + '%29' +
'%28' + 'argument' + '%29' +
'&arg=' + encodedContent
// EXECUTE THE URL
await craft.editorApi.openURL(url);
});
</script>
</body>
</html>
1 Like
Sal
December 6, 2021, 4:28pm
#11
Because security is always a primary concern, the first run of an external URL will require explicit approval by the user. If you select the automatic execution checkbox in the security approval dialog, the script will no longer require approval.
Sal
December 6, 2021, 4:32pm
#12
Here is the extension file:
of-new-task.craftx.zip (69.5 KB)
1 Like
zsombor
December 6, 2021, 4:36pm
#13
re: Speech Recognition: I do not know the answer to. Interestingly It works in Safari for me in the Web Editor
This might be relevant (though not an answer )
Suggests there might be a permission issue in MacOSx that is not there in web speech use.
This might be the answer:
https://talkrapp.com/speechSynthesis.html
(read down past the list of voices)
Speech synthesis has to be user initiated and will not autorun.
“The end result is that you can only play text to speech when the user clicked on something to initiate the action.” There’s some suggested code to help deal with this.
Things are never easy!
1 Like
Sal
December 6, 2021, 6:54pm
#16
How to get the actual text string from the selection? I’m getting undefined from this code:
result = await craft.editorApi.getTextSelection()
if (result.status !== "success") {
throw new Error(result.message)
}
selectedText = result.data
Sal
December 6, 2021, 7:47pm
#17
The result of craft.editorApi.getSelection()
returns an array of data objects describing the selected blocks, like this:
[{"id":"F3020F5C-8B30-43F0-B679-74C13BDD62DD","hasBlockDecoration":false,"color":"text","indentationLevel":0,"spaceId":"859c432e-33f3-7983-7c20-67a12bd618aa","subblocks":[],"content":[{"isItalic":false,"isStrikethrough":false,"text":"HOW NOW BROWN COW","isCode":false,"isBold":false}],"type":"textBlock","listStyle":{"type":"none"},"documentId":"A189DCF5-E6AC-4ADB-B451-2E666CA6A07F","style":{"fontStyle":"system","alignmentStyle":"left","textStyle":"body"},"hasFocusDecoration":false}]
However, attempts to extract the resulting text fail and return undefined:
result = await craft.editorApi.getSelection()
result.data[0]["text"] <-- fail
result.data[0].text <-- fail
What is the “magic syntax" to get the text of the selected block? Thanks!
Sal
December 6, 2021, 10:39pm
#18
Ah. There are two “text” keys:
blockID = passedData[0].id
blockText = passedData[0].content[0].text
Getting closer…
Sal
December 6, 2021, 11:16pm
#19
Here’s a fully working Craft extension that creates a new task in OmniFocus using the text of the first selected block. The OmniFocus task note will contain a link-back to the block in the Crafts document.
of-new-task.craftx.zip (70.0 KB)
<!DOCTYPE html>
<html>
<body>
<button id="btn-execute">OmniFocus Task with Block</button>
<p>This Crafts extension will create a new Task in OmniFocus using the text data of the first selected block. The OmniFocus task note will contain a link-back to the block in the Crafts document.</p>
<script>
// CREATE/SEND OMNI AUTOMATION SCRIPT URL
// DOCUMENTATION: https://omni-automation.com/script-url/index.html
const button = document.getElementById("btn-execute");
button.addEventListener("click", async () => {
try {
// GET THE SELECTED TEXT
result = await craft.editorApi.getSelection()
if (result.status !== "success") {
throw new Error(result.message)
} else {
var selectedBlockData = result.data
}
if(selectedBlockData !== ""){
// FUNCTION TO BE EXECUTED BY OMNIFOCUS
function newOmniFocusTask(passedData){
console.log(passedData)
blockID = passedData[0].id
spaceID = passedData[0].spaceId
documentID = passedData[0].documentId
blockType = passedData[0].type
blockText = passedData[0].content[0].text
if (blockText.length > 24){
taskTitle = blockText.substring(0, 24) + "..."
} else {
taskTitle = blockText
}
linkURL = `craftdocs://open?blockId=${blockID}&spaceId=${spaceID}`
tsk = new Task(taskTitle)
tsk.note = linkURL + "\n\n" + blockText
URL.fromString(`omnifocus://task/${tsk.id.primaryKey}`).open()
}
// CREATE FUNCTION AND CONTENT STRINGS
contentString = JSON.stringify(selectedBlockData)
encodedContent = encodeURIComponent(contentString)
functionString = newOmniFocusTask.toString()
encodedFunction = encodeURIComponent(functionString)
// CREATE SCRIPT URL
url = 'omnifocus://localhost/omnijs-run?script=' +
'%28' + encodedFunction + '%29' +
'%28' + 'argument' + '%29' +
'&arg=' + encodedContent
// EXECUTE THE URL
await craft.editorApi.openURL(url)
} else {
throw new Error("No text is selected.")
}
}
catch(err){
throw `${err.name}\n${err.message}`
}
});
</script>
</body>
</html>
1 Like
Sal
December 6, 2021, 11:17pm
#20
And here’s what a new task looks like in OmniFocus:
1 Like
Sal
December 7, 2021, 6:21am
#21
Here’s an updated archive. This version has a formatted description and button:
of-new-task.craftx.zip (70.2 KB)
1 Like