I have a CEP extension in After Effects and I want it so that when a user clicks a button, a settings dialog opens up in a new floating dialog box. Seems like it would be such basic functionality but somehow I'm not seeing anywhere in the (admittedly sparse) documentation how to open up a dialog box. I've seen some other people say that you can make a hidden extension which opens the dialog, but I've seen no example of that and it is unclear how that would work to me.
You can look up documentation for ScriptUI. Heres a link to the pdf: https://adobeindd.com/view/publications/a0207571-ff5b-4bbf-a540-07079bd21d75/92ra/publication-web-resources/pdf/scriptui-2-16-j.pdf
You can create a dialog either in a function in the jsx, or give it its own jsx page and //#include it onclick.
I know this is kind of a generic answer, but incase anyone else is having trouble this will give you a good jumping off point.
So in order to provide the functionality you need, you'll have to initialize a dialog box first, then add a button, then force it to open a specific settings dialog. I recommend something like this:
var dialog = new Window("dialog");
dialog.text = "After Effects Dialog Script";
//Contents
var newMsg = dialog.add("group", undefined, {name: "newMsg"});
newMsg.orientation = "column";
var newMsgText = newMsg.add("statictext", [0, 0, 400, 40], "", {name: "newMsgText", multiline: true});
newMsgText.text = "Would you like to open a settings dialog?";
//Button UI
var buttonPanel = dialog.add("group", undefined, {name: "buttonPanel"});
buttonPanel.orientation = "row";
buttonPanel.alignChildren = ["center", "bottom"];
var enter = buttonPanel.add("button", undefined, undefined, {name: "ok"});
enter.text = "Continue";
enter.value = true;
var cancel = buttonPanel.add("button", undefined, undefined, {name: "cancel"});
cancel.text = "Cancel";
cancel.value = false;
//Runs the dialog code
dialog.show();
//Grabs answer to yes or no question
var dialogInput = dialog.show();
if(dialogInput == true){
app.openDlg (prompt, filter, multiSelect); //Essentially
}
else {
alert("The action was canceled.");
}
You will have to find the direct path to the CEP dialog you wish to open. I'm unfamiliar with them and their integrations to After Effects, so I can't help you much beyond getting the script set up. However I have a few comments on resources that may be of assistance here too.
That ScriptUI resource by Peter Kahrel is fantastic. I've been working with it for the last few weeks. I wanted to add on to what Jake L said by dropping in a few more great examples of Extendscript Support because you kinda have to dig for the documentation, but it's definitely there.
https://extendscript.docsforadobe.dev/
I just stumbled upon the Extendscript Library recently, but it details a lot of functions, dives deep into events and event handlers, and even explains how you can set up an environment for extendscript via vscode.
I also like to check out NTProductions on youtube for assistance. I'm working in Indesign, but a lot of the extendscript functions work between the various adobe programs and you can even troubleshoot basic functions in the Adobe ExtendScript Toolkit.
And if you already have an Adobe CC account, don't forget to download the Scripting SDK from adobe APIs and Services. You'll have to sign in to get there, but it's a pretty useful local documentation.
https://developer.adobe.com/console/servicesandapis/id#
EDIT (again): I also found these after posting and will commit to adding more as I find them. Extendscript documentation must become more available! :-)
https://docsforadobe.dev/
http://yearbook.github.io/esdocs/#/
Related
I have setup an interactive PDF form with a Javascript button to submit the form by email, extracting data input by the user. The button works fine in Adobe Reader but does nothing in NitroPDF. Is there a problem with the code (see below)?
var cToAddr = this.getField("ComboBox1").value
var cSubLine = "Property Transaction Form " + this.getField("Text1").value
var cBody = "The attached file is the filled-out form. Please open it to review the data."
this.mailDoc({bUI: true, cTo: cToAddr, cSubject: cSubLine, cMsg: cBody})
With the plethora of PDF viewers out there that implement only some of the Acrobat JavaScript API - some more, some less - I recommend testing for the existence of any functions that your document requires before trying to use them. Wrap your code in the snippet below to let the user know that they are using a less capable viewer than what you've programmed the document for.
if (typeof this.mailDoc == 'function') {
// The viewer can mail documents
}
else {
// Warn the user somehow
}
I've forked a Gnome Shell Extension, as I want to modify it to fit my personal preferences. I want to send a notification each time an event occurs. Sending the notification itself is fairly easy with Main.notify(summary, text). However, I just can't find out how to set a custom icon. [EDIT: The following is wrong. I looked up bad code]According to the github repo of gnome-shell I can define an icon via an optional parameter: Main.notify(summary, text, params), where params will be checked in MessageTray.js l.367:
params = Params.parse(params, { gicon: null,
secondaryGIcon: null,
bannerMarkup: false,
clear: false,
soundName: null,
soundFile: null });
if (params.gicon || params.clear)
this.gicon = params.gicon;
So I tried to use the following command:
Main.notify(summary, text, {gicon: myicon});
But the {gicon: myicon} part is ignored completely and the default icon is used :-/.
I'm new to Javascript and GNOME programming, so pls don't hate me :-)
Is using Main.notify() recommended generally, or is it deprecated?
Cheers, Maphardam
I think that Main.notify() is generally recommended, as it is used in some of the "official" extensions.
However, Main.notify() only takes two parameters (msg, details) and thus you cannot use this function to set a custom icon.
You can however copy the source of Main.notify() and adapt it to your own needs. Inside the following function the source of the notification is set to a newly created source with a custom icon.
function notify(msg, details, icon) {
let source = new MessageTray.Source("MyApp Information", icon);
Main.messageTray.add(source);
let notification = new MessageTray.Notification(source, msg, details);
notification.setTransient(true);
source.notify(notification);
}
For example you could call it with notify("MyApp", "Test", 'folder-symbolic');.
This is a really strange one. Our company has has an InDesign script that, near the end, calls Acrobat (by way of Applescript) to open a PDF file, replace a page in it, then save the file and close it. We've been using this script for over a year and a half now with no issues on 8 of the 9 computers we have. That last one, however, is giving me an odd message when it tries to open and save the file.
To be clear, all 9 computers are Macs, all running OS X 10.9.5 Mavericks. The script is on a central server, so they're all using the same file:
var unlockCover2014 = app.trustedFunction(function (fName, fPrefix)
{
app.beginPriv();
var folderPrefix = fName.match(/^.*?(?=JOBS)/);
console.println("fName is " + fName);
console.println("folderPrefix is " + folderPrefix);
var myDoc = app.openDoc(folderPrefix + "Product Templates/ProofCoverNew/proof_cover_2014.pdf");
myDoc.replacePages(0, fName, 0, 0);
myDoc.saveAs(fName);
myDoc.closeDoc(true);
app.endPriv();
});
This file is stored in the correct folder to be a Folder-level script. 8 of the computers work through this without any trouble whatsoever. The 9th, however, puts this into Acrobat's Javascript console:
fName is /ArtDept/ArtDept/JOBS/425000-425999/425000 Folder/425000_cover.pdf
folderPrefix is /ArtDept/ArtDept/
RaiseError: This file is already open.
Doc.saveAs:9:
===> This file is already open.
I do not understand why this computer, alone, thinks that the PDF files are open already. The problem that arises from this is that, when the main InDesign script is done running, two documents are still open in Acrobat, and the one it's supposed to save does not get saved.
Any ideas about what's going on here?
I did finally discover what the problem was. I feel a bit silly about how (almost) obvious it is, but perhaps it might help others in my situation.
I disabled the line in the main InDesign script that was calling Acrobat, figuring I'd come back to that problem later after I dealt with some other issues. When I did so and ran the main script again, I discovered that Acrobat does, in fact, already open up a copy of that cover sheet PDF sometime during the execution of the main script! I was shocked, at first, but then I did a headdesk when I quickly realized the cause:
InDesign on this computer is set, by default, to automatically open a PDF after exporting it.
So, I just added a short line to the part of my code that sets the PDF Export Preferences to turn that feature off:
with (app.pdfExportPreferences)
{
pageRange = proofRange;
if (multiColor) pageRange = colorTable.toString();
useSecurity = true;
disallowChanging = true;
disallowCopying = false;
disallowDocumentAssembly = true;
disallowExtractionForAccessibility = false;
disallowFormFillIn = true;
disallowHiResPrinting = false;
disallowNotes = true;
disallowPlaintextMetadata = true;
disallowPrinting = false;
changeSecurityPassword = "(NOPE)";
viewPDF = false;
}
It's the viewPDF line at the end. (Sorry, I don't think I can highlight it with markdown.) I do feel silly that I overlooked such a semi-obvious cause, but I hope this might help someone else who is experiencing a similar issue. Thanks for trying to help anyway, #Loic.
Is it possible that the Acrobat script is ran while InDesign has not totally ended writing the PDF File if this is what we are talking about ? Or maybe there are some network latencies that make the file not reachable for the moment.
I would advice using a delay to (in)validate that theory.
delay 3
On another end, why do you need to replace file. I mean can't this be thought in InDesign Scripting Scope only ? Just curious.
Is it possible, using javascript, to control an overlay firefox extension? I've extracted the contents of the extension and have identified what functions/methods I need to run, but they are not accessible within the scope of the console.
Thanks in advance for any ideas.
Yes it possible to interact with other add-ons, given the right circumstances.
My test case here will be com.googlecode.sqlitemanager.openInOwnWindow(), which is part of the SqliteManager addon.
In newer builds (I'm using Nightly), there is the Browser Toolbox. With it is is as simple as opening a toolbox and executing com.googlecode.sqlitemanager.openInOwnWindow() in the Console.
You may instead use the Browser Console (or any chrome enabled WebDev Console for that matter, e.g. the Console of "about:newtab"). But you need some boilerplate code to first find the browser window. So here is the code you can execute there: var bwin = Services.wm.getMostRecentWindow("navigator:browser"); bwin.com.googlecode.sqlitemanager.openInOwnWindow()
Again, enable chrome debugging. Then open a Scratchpad and switch to Chrome in the Environment menu. Now executing com.googlecode.sqlitemanager.openInOwnWindow() in our Scratchpad will work.
You may of course write your own overlay add-on.
As a last resort, patch the add-on itself.
Bootstrapped/SDK add-ons: you can load XPIProvider.jsm (which changed location recently) and get to the bootstrapped scope (run environment of bootstrap.js) via XPIProvider.bootstrapScopes[addonID], and take it from there (use whatever is in the bootstrap scope, e.g. the SDK loader).
Now about the right circumstances: If and how you can interact with a certain add-on depends on the add-on. Add-ons may have global symbols in their overlay and hence browser window, such as in the example I used. Or may use (to some extend) JS code modules. Or have their own custom loader stuff (e.g. AdBlock Plus has their own require()-like stuff and SDK add-ons have their own loader, which isn't exactly easy to infiltate)...
Since your question is rather unspecific, I'll leave it at this.
Edit by question asker: This is correct, however I figured I'd add an example of the code I ended up using in the end, which was in fact taken directly from mozilla's developer network website:
In my chrome js:
var myExtension = {
myListener: function(evt) {
IprPreferences.setFreshIpStatus(true); // replace with whatever you want to 'fire' in the extension
}
}
document.addEventListener("MyExtensionEvent", function(e) { myExtension.myListener(e); }, false, true);
// The last value is a Mozilla-specific value to indicate untrusted content is allowed to trigger the event.
In the web content:
var element = document.createElement("MyExtensionDataElement");
element.setAttribute("attribute1", "foobar");
element.setAttribute("attribute2", "hello world");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("MyExtensionEvent", true, false);
element.dispatchEvent(evt);
Update for Firefox 47 and up
Things changed drastically in Firefox 47. This is the new way to access it.
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var addonid = 'Profilist#jetpack';
var scope = XPIScope.XPIProvider.activeAddons.get(addonid).bootstrapScope
Old way for < Firefox 47
Update for methods of today
Typically you will do so like this:
If i wanted to get into AdBlocks scope, I check AdBlock id, it is {d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d} so I would go:
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var adblockScope = XPIScope.XPIProvider.bootstrapScopes['{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}'];
You can now tap into anything there.
Another example, I have an addon installed with id NativeShot#jetpack
I would tap into it like this:
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var nativeshotScope = XPIScope.XPIProvider.bootstrapScopes['NativeShot#jetpack'];
if you do console.log(nativeshotScope) you will see all that is inside.
I am developing a Firefox addon and I was wondering how to get the contents of the search box in the toolbar using the Mozila Addon SDK? I finally found the chrome URL where it resides (at least I think: chrome://browser/content/search/...), but I’m still a little unsure as to how to reference this to get the contents of the search box into my addon. I tried: document.getAnonymousElementByAttribute(this, "anonid", "searchbar-textbox"); but this gives a “document is not defined” error, probably because Firefox has no idea what ‘searchbar-textbox’ is and this is outside the scope of the addon (in a different ‘document’). I’m relatively new to addon development, so there’s probably a fairly straight forward way to do this, it is just that this solution is unknown to me. Thanks.
Your "main" module (and other lib/ modules) do not have any document attached. You need to first use some low-level API such as the window/utils .getMostRecentBrowserWindow() function to obtain the DOMWindow for the active browser window. After that it's just getting the #searchbar element and checking the .value property (exposed through XBL).
Complete example:
const {getMostRecentBrowserWindow} = require("window/utils");
require("sdk/widget").Widget({
id: "log-search-field",
label: "Log Search Field",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function() {
let win = getMostRecentBrowserWindow();
console.error("Search text: " + win.document.getElementById("searchbar").value);
}
});