InDesign Export all TextFrames to JPG or PNG Individually - javascript

I'm struggling with a problem where I need to get JPGs of all the written questions in InDesign since I work at a school. To make the process faster, I decided to go the "Export Objects" way. But i couldn't find a suitable script to achieve what I need.
Basically,
Select All Text Frames in the given Layout(Alternates are present)
Export All Text frames as JPG with given DPI value and name variable.
Both actions are actually available with the Sample codes, but in a different way. For example: SelectObject script works, but when combined with Command+E, the export result is one big image that contains all the selected frames. I want them separately.
I've tried combining the scripts given as applescript or js with my little knowledge of coding but no cigar.
Select Text : Indesign CC 2018 - SelectObjects Sample Code.
Image export: Indesign CC 2018 - Export to JPG scripts are the codes I've tried mingling with.
Goal: Export all text frames individually as variable DPI, variable name and variable destination from separate alternate layouts.
Edit 1: Code that I'm trying to mingle with. I found it on reddit but even though it essentially does what i need, it does in a crooked way and unusable. IT exports ALL items and they are with the page background, I'd need only the stuff that are contained within the TextFrame.
// Set resolution options
var rp = [72,150,300];
// Set EXPORT presets
app.pngExportPreferences.exportResolution = 72;
app.pngExportPreferences.antiAlias = true;
app.pngExportPreferences.pngQuality = PNGQualityEnum.MAXIMUM;
app.pngExportPreferences.pngColorSpace = PNGColorSpaceEnum.RGB;
app.pngExportPreferences.pngExportRange = PNGExportRangeEnum.EXPORT_RANGE;
// Resolution Select Dialog
var w;
w = new Window('dialog', 'Export Presets');
w.orientation = 'row';
with (w)
{
w.sText = add('statictext', undefined, 'Select Export Resolution:');
w.dropdown = add ( 'DropDownList',undefined,undefined,{items:rp});
w.btnOK = add('button', undefined, 'OK');
};
w.dropdown.selection=0;
w.show();
// Set resolution
var x = 0;
x = x + w.dropdown.selection;
app.pngExportPreferences.exportResolution = rp[x];
// SElECT Folder locations
var myFileAmount = 0;
var myFileLocation = Folder.selectDialog("Please select path of InDesign Files");
myFolder = new Folder ([myFileLocation]);
myFolderContents = myFolder.getFiles("*.indd"); // array
myFileAmount = (myFolderContents.length - 1);
// CHECK IF FILES IN FOLDER
if (myFileAmount < 0){alert("No Files in selected folder");}
else
{
var mySaveLocation = Folder.selectDialog("Please select path to Save PNG");
mySaveFolder = new Folder ([mySaveLocation]);
// OPEN FILES One at a time
for (i = myFileAmount; i >= 0; i--)
{
app.open(File (myFolderContents[i]));
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
// SET Active Document
var myDoc = app.activeDocument;
// EXPORT
//One Page at a time
for (var p=0; p < myDoc.pages.length; p++)
{//page loop
var pname = myDoc.pages.item(p).name;
//set all items in file hiden
for (var itemnum=0;itemnum < myDoc.pages.item(p).pageItems.length; itemnum++)
{
myDoc.pages.item(p).pageItems.item(itemnum).visible = false;
}
// set page to export
app.pngExportPreferences.pageString = pname;
//add a 0 in from on less than 10
if (p<9){var pnm=0;}else{var pnm=""}
//LOOP Through items Set Visibility, export a PNG, Set Visibility
for (var itemexport=0;itemexport < myDoc.pages.item(p).pageItems.length; itemexport++)
{
var itm = itemexport+1;//items start at 1 not 0
myDoc.pages.item(p).pageItems.item(itemexport).visible = true;
//ACTUALLY EXPORTING
app.activeDocument.exportFile(
ExportFormat.PNG_FORMAT,
File(mySaveFolder.fsName + "/" + app.activeDocument.name.split(".indd")[0] + "_"+ pnm + pname + "_" + itm +".png"),
false,
);
//SET VISIBILITY
myDoc.pages.item(p).pageItems.item(itemexport).visible = false;
}
}
app.activeDocument.close(SaveOptions.no);
}
}

Related

Photoshop Script Select all visible Artboards

I've been trying to find a way to select all visible artboards, so i can later Quick Export them all as PNGs. I'd also love if i've could also include the exporting part inside the script, but that's not the main problem now.
I have this code that finds all the visibile artboards and stores them inside visibleArtboards, but I can't seem to find a way to make a selection of them.
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++){
if(artboards[i].visible){
visibleArtboards.push(artboards[i]);
}
}
activedoc.activeLayer can make a selection, but only of 1 single artboard.
If anybody can help me with the missing piece, I'd appreciate it a lot
You can get the layer ID of the artboards and add that to a selection. Using your code, visibleArtboards now is the ID of the artboard layers.
// call the source document
var activeDoc = app.activeDocument;
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++)
{
if(artboards[i].visible)
{
// select ID as we go along
var layerID = artboards[i].id;
visibleArtboards.push(layerID);
}
}
// Loop over the layers again and select all the art boards
for (var i=0; i<visibleArtboards.length; i++)
{
// add to current selection of layers
select_by_ID(visibleArtboards[i], true);
}
function select_by_ID(id, add)
{
if (add == undefined) add = false;
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putIdentifier(charIDToTypeID('Lyr '), id);
desc1.putReference(charIDToTypeID('null'), ref1);
if (add) desc1.putEnumerated(stringIDToTypeID("selectionModifier"), stringIDToTypeID("selectionModifierType"), stringIDToTypeID("addToSelection"));
executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
} // end of selectByID()
It will, however, add the background (if included). I'm sure you can get around that.

How to use a same image multiple times by loading it only once when I need different id for every element

I am a newbie to programming and web developing. The project I am doing is only for practice, if my approach seems ameteur to you, please suggest any better options.
I am trying to develop a parking lot booking system. And in the UI, I want to show all the empty/filled slots (like it is while booking movies or bus tickets).
I couldn't find a top view icon of a car, so I thought of using an image instead of icon.
But as of the image, if I use say 50 images on a single page, the page will get very heavy.
But one important thing is that I need all the elements as seperate entities, only then I will be able to book them with their id(unique address). So I want 50 different divs with seperate distinct ids but want to use only one image for all the slots, or a maximum of 2 different images(keeping the directions in mind).
how to display same image multiple times using same image in javascript
I went through this answer, and found a piece of code that might be useful:
var imgSrc = 'http://lorempixel.com/100/100';
function generateImage() {
var img = document.createElement('img')
img.src = imgSrc;
return img;
}
for (var i = 0; i < 20; i++ ) {
document.body.appendChild(generateImage());
}
While I can make use of a function and a loop in javascript to create as many copies of one image, I don't know how to alot them to the different div tags with distinct ids.
use a function :)
const addMessage = (element, msg, cls) => {
const patt = new RegExp("<");
const messageElement = document.createElement("div");
if (patt.test(msg)) {
messageElement.innerHTML = msg
} else messageElement.textContent = msg;
if (cls) messageElement.classList.add(cls);
element.appendChild(messageElement);
}
const imgPath = "/somepath";
const body = document.querySelector("body");
addMessage(body, `<img src=${imgPath} class="whatever">`, "img1"); //creates new divs with classes. the 3rd arg is optional
the best approach for this is the client side already receiving all this content as a string but as it made clear that it is for study I deduce that it is not the intention to use back end to solve this problem
let allContent = '';
for (var i = 0; i < 20; i++ ) {
allContent += `<div class="wrapper-image"><img src="/path"></div>`
}
document.getElementById('idWrapper').innerHTML = allContent;
speaking in performace the browser will only download the image once, so you can use it as many times as you like, which is disruptive to the changes you make in the DOM (remove, add or edit a content)
In my example you create all the content to be displayed on the page and then add it in a single time, it is not too bad if it is performace but the ideal is to do it on the back side
in the DIV you can put an image address of a variable to do some logical type this:
let allContent = '';
let imgOne = '/oneimg';
let imgOne = '/twoImg';
for (var i = 0; i < 20; i++ ) {
if(i>10){
allContent += `<div class="wrapper-image"><img src="${imgOne}"></div>`
}else {
allContent += `<div class="wrapper-image"><img src="${twoImg}"></div>`
}
}
document.getElementById('idWrapper').innerHTML = allContent;

Photoshop Script Processing Images Out of Order

I am running javascript via Photoshop's scripts tool/option in order to batch process a folder of images. The script adds a second image layer from a single image in folder 02 to a number of images in folder 01. That works fine, however, I am trying to decrement the opacity of the layer that is added, so that the image that is added from folder 02 is increasingly more transparent for each subsequent image processed from folder 01. I'm basically creating a fade that transitions from the image in folder 02 to revealing the images processed from folder 01. The opacity change is happening as expected (decrementing opacity for each processed image); however, they seem to get processed out of order, so as I view the images in order, the opacity of that added layer jumps around. I can also see that as the newly processed images save to the processed image folder, they arrive out of order (something like 1, 3, 2, 5, 6, 4; though it might be different each time). I suspect I need to force my code to process the images one at a time in order, but I'm not sure how to go about that. Thanks in advance! I don't believe file naming is the issue since I've tried naming the images in folder 01 as both 1, 2, 3, (and so on) as well as 01, 02, 03. But that doesn't help.
Thanks in advance!
#target photoshop
// FOLDERS
var folder1 = new Folder('~/Desktop/1/');
var folder2 = new Folder('~/Desktop/2/');
var saveFolder = new Folder('~/Desktop/done/');
//
var searchMask = '*.???'; // get files named as this
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
var psdOptions = new PhotoshopSaveOptions();
psdOptions.layers = true;
opacityLevel = 100;
for (var i = 0; i < list1.length; i++) {
var doc = open(list1[i]);
var docName = doc.name;
placeFile('~/Desktop/2/1.jpg', 100); // for adding only one file each source file
doc.activeLayer.blendMode = BlendMode.LIGHTEN; // ## change BLEND MODE
placeFile('~/Desktop/2/2.png', 100); // for adding only one file each source file
doc.activeLayer.blendMode = BlendMode.MULTIPLY; // ## change BLEND MODE
doc.activeLayer.opacity = opacityLevel; // set layer opacity
// Decrement opacity level for each image
if (doc.activeLayer.opacity > 5) {
opacityLevel = Math.round(doc.activeLayer.opacity) - 5;
}
// SAVING
doc.saveAs(new File(saveFolder + '/' + docName.split('.')[0] + '.psd'), psdOptions);
doc.close(SaveOptions.DONOTSAVECHANGES);
};
function placeFile(file, scale) {
try {
var idPlc = charIDToTypeID("Plc ");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc2.putPath(idnull, new File(file));
var idFTcs = charIDToTypeID("FTcs");
var idQCSt = charIDToTypeID("QCSt");
var idQcsa = charIDToTypeID("Qcsa");
desc2.putEnumerated(idFTcs, idQCSt, idQcsa);
var idOfst = charIDToTypeID("Ofst");
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID("Hrzn");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idHrzn, idPxl, 0.000000);
var idVrtc = charIDToTypeID("Vrtc");
var idPxl = charIDToTypeID("#Pxl");
desc3.putUnitDouble(idVrtc, idPxl, 0.000000);
var idOfst = charIDToTypeID("Ofst");
desc2.putObject(idOfst, idOfst, desc3);
var idWdth = charIDToTypeID("Wdth");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idWdth, idPrc, scale);
var idHght = charIDToTypeID("Hght");
var idPrc = charIDToTypeID("#Prc");
desc2.putUnitDouble(idHght, idPrc, scale);
var idAntA = charIDToTypeID("AntA");
desc2.putBoolean(idAntA, true);
executeAction(idPlc, desc2, DialogModes.NO);
}
catch (e) { }
}//end function placeFile
Never count on file list functions to maintain a logical order...
Try sorting the file lists after creating them.
var list1 = folder1.getFiles(searchMask);
var list2 = folder2.getFiles(searchMask);
list1.sort();
list2.sort();
Make sure the filenames sort ascibetically. Zerofix if you use numbers.
Alternatively, you can supply Array.sort() with a sorting function to allow for a custom sorting. Read more about how that works here.

Photoshop script won't save file with percentage symbol in the name

I have this script that I am running via photoshops Scripts Event Manager that looks for files with ".jpg" and then saves them for web and reduces the quality to 70%.
It runs absolutely fine until it hits a file with a percentage in the name eg. Background_(25%).jpg. Is there anyway i can alter this script so that i can reduce the quality of these jpgs as well as the ones i am already hitting?
Thanks
var imageFolder = Folder.selectDialog("Select the folder with JPGs to process");
if (imageFolder != null) processFolderJPG(imageFolder);
function processFolderJPG(folder) {
var fileList = folder.getFiles()
for (var i = 0; i < fileList.length; i++) {
var file = fileList[i];
if (file instanceof File && file.name.match(/\.jpg$/i)) {
open(file);
var docJPG = app.activeDocument;
var strtRulerUnitsJPG = app.preferences.rulerUnits;
var strtTypeUnitsJPG = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
var saveFileJPG = new File(decodeURI(activeDocument.fullName.fsName));
saveFileJPG.remove();
SaveForWebJPG(saveFileJPG,70); // set quality to suit
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
app.preferences.rulerUnits = strtRulerUnitsJPG;
app.preferences.typeUnits = strtTypeUnitsJPG;
} else
if (file instanceof Folder) {
processFolderJPG(file);
}
}
}
function SaveForWebJPG(saveFileJPG,jpegQuality) {
var sfwOptionsJPG = new ExportOptionsSaveForWeb();
sfwOptionsJPG.format = SaveDocumentType.JPEG;
sfwOptionsJPG.includeProfile = false;
sfwOptionsJPG.interlaced = 0;
sfwOptionsJPG.optimized = true;
sfwOptionsJPG.quality = jpegQuality;
app.activeDocument.exportDocument(saveFileJPG, ExportType.SAVEFORWEB, sfwOptionsJPG);
}
EDIT: I need the files to remain the same filename.
I couldn't reproduce your error, supposedly, its reason is somewhere near the decodeURI function – % symbols usually take place in the beginning of many symbols, like
Encoded URI: en.wikipedia.org%2Fwiki%2F95%25_Confidence_interval
Decoded URI: en.wikipedia.org/wiki/95%_Confidence_interval
Without any additional information given, I'd try this:
file.name.replace('%', '').match(/\.jpg$/i))
p.s. maybe this and this questions would be helpful (especially the second one)

JavaScript OO Programming and passing variable to PHP

Using Joomla custom output module to display articles for a category, but have limited space.
Here is the test site: http://cshtest.camdendiocese.org/
In the footer you'll see the third of 4 columns has data. It scrolls forward and backwards using JavaScript. But as you see it has 4 columns, all of which work the same on different categories.
I'm having trouble with creating the other columns because they all will need to use separate data items, hence separate modules. I was trying to create an object but got stopped specifying a JavaScript object inside PHP.
Here is the JavaScript that is working:
// This script provides forward and backward paging for article intros in footer-1
// create an array of strings
// Each array element is initalized at this time to establish global scope
var mytexts = [];
mytexts[0] = "<h2>this is text string one</h2>";
mytexts[1] = "<h2>this is text string two</h2>";
mytexts[2] = "<h2>this is text string three</h2>";
// initialize variables
var txtNum = 0;
var txtLength = mytexts.length - 1;
// function to change string
function changeText(direction, col) {
// get next text number
txtNum = txtNum + direction;
// make sure we loop
if (txtNum > txtLength) {
txtNum = 0;
}
if (txtNum < 0) {
txtNum = txtLength;
}
// change the src attribute of the image
var colx = "col-" + col;
document.getElementById( colx ).innerHTML = mytexts[txtNum];
return false; // prevent default link
}
Here is the constructor I made to try to make an object:
function CatArticles(x0, x1, x2) {
// This script provides forward and backward paging for article intros in footer-1
// create an array of strings
// Each array element is initalized at this time to establish global scope
this.mytexts = [];
this.mytexts[0] = x0;
this.mytexts[1] = x1;
this.mytexts[2] = x2;
// initialize variables
this.Num = 0;
this.txtLength = this.mytexts.length - 1;
this.changeText = changeText;
}
// function to change string
function changeText (direction, col) {
// get next text number
this.Num = this.Num + direction;
// make sure we loop
if (this.Num > this.txtLength) {
this.Num = 0;
}
if (this.Num < 0) {
this.Num = this.txtLength;
}
// change the src attribute of the image
var colx = "col-" + col;
document.getElementById( colx ).innerHTML = this.mytexts[this.Num];
return false; // prevent default link
}
I can instantiate the object with script tags in PHP but can't think how to get the variable created in the html to be output. Do you have a suggestion or approach?
If I understand well, considering they are two different scripts, server side and client side another, the solution would be to use ajax for interaction, after the page has already been generated by php.

Categories