Adobe Acrobat Pro DC JavaScript field properties not propagating - javascript

I have been brought in mid stream on an Adobe Acrobat Pro DC customization project. The goal of this project is to add a warning along the left edge of each page. I have been given a piece of JavaScript that does this with one exception and asked to fix that exception.
The code is:
var inch = 72;
for (var p = 0; p < this.numPages; p++) {
var aRect = this.getPageBox( {nPage: p} );
aRect[0] = 8.25*inch; //how far from the left the box ends
aRect[1] = 0.5*inch; //how high from the bottom the box is
aRect[2] = 7.75*inch; //how far from the left the box starts
aRect[3] = 11.0*inch; //how tall the box is
var f = this.addField("ControlledDoc", "text", p, aRect )
f.rotation = 270;
f.delay = true;
f.textSize = 7.5;
f.textFont = font.HelvB;
f.textColor = color.red;
f.alignment = "center";
f.readonly = true;
f.display = display.visible;
f.delay = false;
}
var myWillSaveScript = 'var f = this.getField("ControlledDoc"); \r'
+ 'f.value = "This is an electronic controlled copy of a paper based document management system. When printed on the copy machine it becomes an uncontrolled paper copy valid until the end of the printing day."; \r';
this.setAction("WillSave", myWillSaveScript);
The problem presents when a document is more than one page in length. The ControlledDoc field is replicated on each page as expected. Each page gets a ControlledDoc#n-1 field, where n is the page number. On the first page, the f.rotation setting is retained and shows up in the UI as the Orientation dropdown in the Properties dialog being set to 270. However, on the second and subsequent pages the Orientation is set to 0. I can manually edit the document and set the Orientation to 270, but that defeats the purpose of automating things with JavaScript.
I am new to controlling Acrobat Pro DC with JavaScript, so I will not be surprised if I am missing something stupid...
What do I need to change to make the rotation setting stick on the second and subsequent pages?

Field properties can be on a field level (the same for all copies of the field, with the same nam), or on a widget level (can be different from copy of the field to copy of the field).
The Acrobat JavaScript documentation has a list of those properties. Unfortunately, those two lists (field level and widget level) do not contain the rotation property. That means, we do not really know whether it is field or widget level. From your description, I get the feeling that it is widget level.
What you may try is to create an individual field for every page. You would do that with the line
var f = this.addField("ControlledDoc." + p, "text", p, aRect) ;
About the delay property: I always use the doc.delay property (instead of the field.delay), and because of that outside of a loop, so that it can provide maximum performance gain. However, if the script exits from within the loop, I would have to set delay to false via the Console. From my experience, this will create all appearances (but in order to find out, we'd have to get onto that page, and then they are created immediately…).

I'm assuming you're on page 1 when you run the script. That's why it looks correct on page one.
The delay property, when false, tells Acrobat to delay updating the appearance of the field until it's set to true. When you add the field to the pages, you're telling Acrobat not to generate appearances until all of the settings are set... that's OK... but then, I suspect, you never visit the subsequent pages so the appearances never get updated for those pages even though the delay property is now set to true. Just pull out the two lines that set the delay property and it should work.

Related

How to create a scripted button in Google Sheets that randomly selects from a cells drop-down menu?

I'm working on a grossly complex and embarrassingly ungraceful spreadsheet that is a crudely crafted prompt-builder for AI image creation tools such as Stable Diffusion. The prompt builder is simply made up of about 40 data-validated drop-down menus that each pull from their respective categorical lists of words and phrases that I have listed elsewhere in the same sheet.
I would like to:
Create a scripted button that would automatically choose random options from the drop-down menus and
Add a probability percentage to each of the drop-down menus so that when the randomize button is pressed, there's a, for example, 100% chance that one option is randomly selected, and a 50% chance that another option will be randomly selected.
The Problem: I created a button, scripted it, and it does not function.
Simplified Editable DEMO of my Prompt Builder
I'm very aware that I'm likely doing this the hard way, and would love to avoid scripting if possible, but am at the end of my limited spreadsheet knowledge. I honestly have no business scripting. Using the script I built currently requires permission for anyone to use, which seems unnecessary to me, but it's the only way I knew to create it. I'm wondering if there's some way around that, maybe with triggers? I suppose that's a separate question...
I'm embarrassed to show this, but this is the script that I cobbled together. Before I added the if statements in trying to add probability, I had it kind of working. It would randomize entries, but some more than others. It was bizarre. Once I added in what I thought was probability code, it completely stopped working. Also, again, this is a simplified version of my actual spreadsheet and script, which had 40 individual data-validated dropdown menus.
My Non-Functioning Script:
function randomSelection() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Prompt Tool Demo");
var cell1 = sheet.getRange("C4");
var cell2 = sheet.getRange("C5");
var cell3 = sheet.getRange("C6");
var values1 = sheet.getRange("K3:K24").getValues();
var values2 = sheet.getRange("L3:L24").getValues();
var values3 = sheet.getRange("M3:M24").getValues();
var randomIndex1 = Math.random();
var randomIndex2 = Math.random();
var randomIndex3 = Math.random();
if (randomIndex1 < 1.0) {
cell1.setValue(values1[Math.floor(Math.random() * values1.length)][0]);
}
if (randomIndex2 < 0.5) {
cell2.setValue(values2[Math.floor(Math.random() * values2.length)][0]);
}
if (randomIndex3 < 0.5) {
cell3.setValue(values3[Math.floor(Math.random() * values3.length)][0]);
}
}

How to keep placeholder images before running function using Array images?

High level - I am trying to build a Slot Machine game using HTML, CSS, and JavaScript. At this current step, my goal is to keep 3 blank images before the user selects the 'SPIN' button which will result in running a function that returns 3 random images from an array.
Here is the current repo: https://github.com/feasible-creative/slotmachine
Here is the current repo running live: https://feasible-creative.github.io/slotmachine/
The JavaScript snippet below works to return a random image, but my code currently has this function twice - the first instance seemingly runs automatically which makes it seem like there is a placeholder image when you first access the app (see second link above). Whereas the second instance runs as designed when the user hits spin. [Eventually all 3 images need to be randomized by the function but I think that is a later step].
imgArray = ['img_1.jpg', 'img_2.jpg', 'img_3.jpg']
function getRandomImg() {
randomIndex = Math.floor(Math.random()* imgArray.length);
selectedImg = imgArray[randomIndex]
document.getElementById('slotResult').src = `./img/${selectedImg}`
slotResult.className = 'casino';
}
getRandomImg();
To troubleshoot - I've tried removing the first instance of the above code, but that just leaves a blank space that is filled once the user hits 'SPIN'.

Photoshop scripting - how to create text layer in one history state

This question Photoshop Script to create text in a bitmap image in Photoshop already has answer how to create text layer in photoshop, but as result in history tab you can see 8-10 history state changes. Is there a way to do the same job, but while changing history only once?
Obviously problem is that mentioned answer first adds a layer to document and then edits it 8-10 times and solution would be to create a layer and edit it's properties and then after it's ready add it to document.
I have searched in Photoshop CC 2014 Javascript Scripting Reference and it lists only 3 methods for ArtLayers methods: add(), getByName() and removeAll().
Function add() creates new layers, adds it and then returns it. So according to Javascript Scripting Reference I don't see how it would be possible to first create a layer and then add it.
I am still asking because possibly I have missed something or there is an official way to do it, but has not made it into the official docs for some reason.
Better late than never, but yes it is possible. You just have to suspend the history state with suspendHistory
Just pass your function as a string in the form of
app.activeDocument.suspendHistory("string", "myFunction()");
The first parameter, as far as I'm aware is the history state string.
As in the example,
// Switch off any dialog boxes
displayDialogs = DialogModes.ERROR; // OFF
app.activeDocument.suspendHistory ("history state", "createText('Arial-BoldMT', 48, 0, 128, 0, 'Hello World', 100, 50)");
function createText(fface, size, colR, colG, colB, content, tX, tY)
{
// Add a new layer in the new document
var artLayerRef = app.activeDocument.artLayers.add()
// Specify that the layer is a text layer
artLayerRef.kind = LayerKind.TEXT
//This section defines the color of the hello world text
textColor = new SolidColor();
textColor.rgb.red = colR;
textColor.rgb.green = colG;
textColor.rgb.blue = colB;
//Get a reference to the text item so that we can add the text and format it a bit
textItemRef = artLayerRef.textItem
textItemRef.font = fface;
textItemRef.contents = content;
textItemRef.color = textColor;
textItemRef.size = size
textItemRef.position = new Array(tX, tY) //pixels from the left, pixels from the top
activeDocument.activeLayer.name = "Text";
activeDocument.activeLayer.textItem.justification = Justification.CENTER;
}
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL

How to detect an empty space on a web page

Is there a way to detect an empty area, without text or images within a web page, using JavaScript?
More precisely, how to determine whether point [x,y] is within a blank area, like in the following example (marked in red)
EDIT: I want to make my question clearer, I'm building an extension which supposed to mark search results as trustworthy or as spam, I want to put my marking at the end of the text of a result item URL.
I also want to do it in a generic way, so it wouldn't work only in Google web page. an example is shown below:
You can test for genuine white space like this :
function isWhiteSpace(coords) {
var element = document.elementFromPoint(coords.x, coords.y);
var whitespace = $(document).add("body, html");
return (whitespace.get().indexOf(element) > -1) ? true : false;
}
where coords is an object with .x and .y properties.
DEMO
document.elementFromPoint(), documented here, is "an experimental technology", so I wouldn't trust my life to it. Test thoroughly on all target platforms.
Edit
For the full detection of all the white you seek, isWhiteSpace() would be the first of two stages. The second stage would be isVisualWhiteSpace() implemented with #remdevtec's approach for example.
As my isWhiteSpace(coords) is inexpensive, you would perform it first and only if it returned false go for the expensive test. You could use the protective property of ||
var isWhite = isWhiteSpace(coords) || isVisualWhiteSpace(coords);
But your real problem will be writing isVisualWhiteSpace(). I can't help with that.
One approach would be to work with a screenshot of the window.
You can use libraries like html2canvas to load a screenshot to a HTML canvas element.
Next, on window.onclick, use the automatic event parameter to get an RGBA array of the clicked coordinate:
var pixelData = canvas.getContext('2d').getImageData(
event.offsetX,
event.offsetY, 1, 1)
.data;
Now if all (or at least the first three) pixelData's items equal 255, it means that this point is white.
if (pixelData[0] == 255 && pixelData[1] == 255 && pixelData[2] == 255) {
// the clicked point is white,
// and if the background-color is white,
// it can be considered an empty point
}
Of course, the down side is that you have to know the background color of the site you're testing, or the background color of the element you click in.
You can build a matrix with width and length of the page.
Set all matrix cells to zero.
Get all elements of the DOM.
Get x, y, width, and height of each element, this link may help
Retrieve the position (X,Y) of an HTML element
Draw the elements in the matrix
for(k=0;k < dom_elements.length;k++) {
for(i=dom_elements[k].y;i < dom_elements[k].length;i++) {
for(j=dom_elements[k].x;j < dom_elements[k].width;j++) {
matrix[i][j] = 1 ;
}
}
}
And finally check if matrix[i][j] is set to zero or 1

Object detection and tracking in javascript

Im Recently new here, we have made for our school project a cell detection. That functions under the microscope and detect the cells from PNG images that come out of our software.
On these images there will be a color detection done from tracking.js and then it returns te X and Y position of the image dimensions of the center of the cell.
Our concerning is that the cells we have under our microscope evolve so we take every minute automatically an image of this. So we have a set of 10 images with cells and also dissapearing and new cells. What would be the best way to identify them as new cells, and the cells still exist in the timeframe to identify them by an ID, and the dissapearing cells remove as object.
A lot of text, lets see what we've got right now.
Now as the detection works fine thats great. For each cell we make a new object with the following code:
var cells = [];
celltrack = function (x, y) {
xoutput = (img.offsetLeft + x);
youtput = (img.offsetTop + y);
cells = new cell('cell');
cells.id = count++;
cells.x = xoutput;
cells.y = youtput;
}
cell = function (type) {
this.type = type;
this.id = 0;
this.x = "x";
this.y = "y";
}
A couple of main questions on this moment:
Is this the correct way to create the objects containing the cell info ?
What is the best way to identify a cell before create of delete a object ?
If a cell has moved, how can we link the cell to the same object with 2 different locations.
Thats it for now, if we have got further improvements in our project we keep you informed.
I assume the problem is:
Every minute you will get an image of cells, then properties of cells will be analyzed, the output is a series (an array) of positions for the cells in the image
You would like to track how cells create/disappear/move between time periods
With those assumptions, I think:
Yes, you can use the cell constructor function defined in your snippet, though normally we will capitalize constructor functions (to indicate they should be used with new keyword, as in Cell). The properties that goes into the newly created object are up to you, now they are type, id, x and y.
I think that depends on the rules of identifying cells, based on the input we have (just positions), I am not sure we have a good solution here. Are there other properties of cells we can consider and extract in each image?
It relates to the last question, but once you can identify cells, you can update the cell objects between time periods, the history of locations for a cell can be kept in the Cell object itself, maybe a property called locations of type Array.

Categories

Resources