in extendscript - Photoshop, I would like my dialog-box check boxes to default to previously used choices ... anyone know if this is possible?
You have two choices.
First choice: Using a //#targetengine
Values can be made persistent over a session using a targetengine.
First script
//#targetengine myengine
var x = 100;
Second script
//#targetengine myengine
$.writeln(x);
If you close Photoshop all of the values will be lost
Second choice: Write to a file.
I wont write an example here. This can be done in so many ways. Plain .txt file. .json file. See this example on how to read and write files.
fabianmoronzirfas has got the right answer.
I will say it could with one script only. That script reads in the previous value stored in a text file in a hardcoded location like C:\temp. If the script cannot file the settings file it'll default to some predetermined value and then store this time around.
Just in case, here is the simple script that saves (and tries to load) your prefs in JSON format to the system temp folder:
// set default values
var prefs = {
file: File(Folder.temp.fsName + "/prefs.json"),
title: "",
length: 0
}
// try to load previous prefs
if (prefs.file.exists) prefs = $.evalFile(prefs.file);
// do something
prefs.title = prompt("Type the title:", prefs.title);
prefs.length = prefs.title.length;
// save the prefs to the file
prefs.file.open("w");
prefs.file.write(prefs.toSource());
prefs.file.close();
Related
I am a bit stuck. I have created a script for Photoshop that opens a PSD file containing a few layers plus a linked one, sort of a template.
So far, I got things working for me by creating a droplet that runs the following steps and scripts:
Opening the file/image that is dropped.
Opening the PSD file (opening template, scripted).
Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action).
Applying the template features to this linked layer which has been updated previously (scripted).
Saves a PNG file (scripted),
And finally, closing up opened image and template documents (recorded action).
All is good so far. But this has a limitation. It will only work on one file at a time, with a specific name, at a specific location. So, for example, for the update linked layer to work, the name of the image must be 1.png inside Downloads folder only, in this case.
So my question is: How can I script this to run an iteration of the update on the linked layer using as source(s) the images dropped onto the droplet, regardless of file types (png, jpg, etc.), name, location, and index the output saved PNG file(s)? (1.png, 2.png, 3.png, and so on.)
I started working on my approach, and the steps previously mentioned:
1 - Opening the file/image that is dropped onto the Photoshop droplet.
This would happen automatically with the file—Photoshop will open the file dropped onto the droplet, thus triggering the specific actions sequence set forth. Step one solved. Next!
2 - Opening the PSD file (opening template, scripted)
With this step, I wrote a script that opens the template file. The first step in the action sequence would be this!
var template = new File("/Users/name/Desktop/Folder/Template.psd"); // Of course, you can have your template file anywhere on your computer as long as the path to find it is correct. I have selected my desktop for testing purposes.
app.open(template);
That was another effortless one. Next!
3 - Updating all smart objects (including the linked layer, but limited by a specific name and location)(not scripted, recorded action)
I needed to ensure that the template would easily find its previously linked layer location for the update for this third step to work. I know there are ways to update this with a script, but I didn't want to tinker with that. It was too much of a hassle for me at this stage and with my limited knowledge. Therefore I've decided to accommodate the necessary so the template would find a familiar file name it would look for when the "Update all Modified Content" action is triggered.
At this stage, there are two files opened in Photoshop, one the initial image that serves as a new source for the template, and the second file the template.psd, which contains the linked layer that needs to be updated with the content of the first file.
First, I have saved a copy of the image using the name that the template would look for when searching for the linked layer's name. Next, I have saved a copy of the template using the location of the first image file to keep the initial template safe from all these actions. And third, I triggered the "Update all Modified Content" action. And voila, everything worked. The initial template had the linked file next to it. So the new template copy would search and find the file next to it, in the same place, folder/location, as it happened on the previews step that helped save it as such.
// The following script will retrieve the path of the opened image and will save a copy that matches the name of the linked layer in the template in the same location.
var image_doc = app.documents[0]; //If two or more documents are opened, this approach will help switch between them.
var image_name = image_doc.name;
var image_path = app.documents[0].path.fsName;
var temp_image = new File("" + image_path + "/" + image_name + "");
var opts, file;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
var image_temp_name = "link.png";
pngFile = new File("" + image_path + "/" + image_temp_name + "");
image_doc.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
// Save a copy of the template.psd in the same location as the image and the link.png file needed to update the linked layer.
var temp_template = new File("" + image_path + "/" + image_name + "");
app.open(template);
var opts, file;
opts = new PhotoshopSaveOptions();
opts.format = SaveDocumentType.PHOTOSHOP;
var template_temp_name = "template.psd";
psdFile = new File(image_path + "/" + template_temp_name);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
// After these Update all Modified Content action
Now, four, five, and six are straightforward:
4 - Applying the template features to this linked layer which has just been updated previously (scripted). Done!
5 - Saves the newly formed template as a PNG file (scripted). Done!
6 - And finally, closing up opened image and template documents (recorded action). Done!
I have a program where a camera is set up to constantly take pictures (about every 10 seconds or so) and the picture is sent to a folder on my server and then another program refreshes that folder constantly so that I always just have the most recent picture in that particular folder.
An HTML document exists that also constantly refreshes, and references that picture location to get and display the newest image.
What I'm trying to do is extract the EXIF data (that I've verified exists when I save the image from the active webpage and look at it's properties). I want to display the DateCreated (I believe this is DateTime) and the Latitude and Longitude (I believe is GPSLatitude and GPSLongitude).
I came across this library, exif-js, which seems like the go-to for most people trying to do this same thing in JavaScript. My code looks the same as the code at the bottom of the README.md file, except I changed out my img id="...." and variable names, (see below). It seems like it should work, but it's not producing any data. My empty span element just stays empty.
Is there an issue with the short time span that the page has before refreshing?
Thanks for any help!
Here's what my code currently looks like (just trying to get the DateTime info). I have also tried the GPSLatitude and GPSLongitude tags.
<!-- Library to extract EXIF data -->
<script src="vendors/exif-js/exif-js"></script>
<script type="text/javascript">
window.onload=getExif;
function getExif()
{
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var time = EXIF.getTag(this, "DateTime");
var img1Time = document.getElementById("img1Time");
img1Time.innerHTML = `${time}`;
});
var img2 = document.getElementById("img2");
EXIF.getData(img2, function() {
var allMetaData = EXIF.getALLTags(this);
var allMetaDataSpan = document.getElementById("Img2Time");
allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, "\t");
});
}
</script>
go into ur exif.js file and then go to line 930 and then change it to
EXIF.getData = function(img, callback) {
if ((self.Image && img instanceof self.Image
|| self.HTMLImageElement && img instanceof self.HTMLImageElement)
&& !img.complete)
return false;
I know this may be already solved but I'd like to offer an alternative solution, for the people stumbling upon this question.
I'm a developer of a new library exifr you might want to try. It's maintained, actively developed library with focus on performance and works in both nodejs and browser.
async function getExif() {
let output = await exifr.parse(imgBuffer)
console.log('latitude', output.latitude) // converted by the library
console.log('longitude', output.longitude) // converted by the library
console.log('GPSLatitude', output.GPSLatitude) // raw value
console.log('GPSLongitude', output.GPSLongitude) // raw value
console.log('GPSDateStamp', output.GPSDateStamp)
console.log('DateTimeOriginal', output.DateTimeOriginal)
console.log('DateTimeDigitized', output.DateTimeDigitized)
console.log('ModifyDate', output.ModifyDate)
}
You can also try out the library's playground and experiment with images and their output, or check out the repository and docs.
I want to draw structure of some chemicals based on values in a log file . So I write a javascript for drawing and it works for predefined x,y,z coordinates value
.txt file contain
its 5th,6th,7th indicates x,y,z coordinates value.
log file contain following fields
is there is any way to browse a file from user and accept those value in 5th,6th,7th field of .txt file.
To get the file uploaded check out kk anu's answer.
Once you have the file in access and can read it, it's a straight forward iteration of each line.
var linesFromFile= file.split(/[ ,]+/);
linesFromFile.forEach(function(entry)
{
var parsedFloat = parseFloat(entry);
if(parsedFloat === Number(parsedFloat) && parsedFloat%1!==0){
// do something with the parsed float
}
});
You have to adapt the code for your needs, but this is basically the function to go with.
I have a local text file which is kept changing by other programs. I want to write a html and javascript based web page to show the content of file dynamically. I have searched in google and found that most solutions require to get this text file via html element. I wonder if there is a way to get the file via a fixed path(lets say it is a string of the file directory) in javascript. I am using Javascript fileReader. Any help will be appreciated.
This is not possible using javascript running inside the browser. You will not be able to do anything outside the browser.
EDIT:
You could run a Node.js server though that runs on localhost and does your file operations you desire. You could build a API so your html page that you load in the browser calls your serverscript to do your file operations.
Do you understand what I mean?
How much information does the text file hold, Depending on your scenario it might be worth looking into javascript localstorage W3SCHOOLS local storage. Would that help your situation ?
What you can do is allow the user to choose the file of interest, using a file-input. Once done, the browser wil have access to the file, even though the JS wont have access to the file's full-path.
Once the user has chosen the file, you can reload it and refresh the view pretty-much as often as you please.
Here's a short demo, using a file input (<input type='file'/>) and an iframe. You can pick pretty much anything the browser will normally display, though there are limits on the size of the file that will work - due to the limit of the length of a URL - the file's data is turned into a data-url and that url is set as the source of the iframe.
As a demo, pick a file and then load it. Now, open the file in another program and change it. Finally, press the load button once again - the new content now fills the iframe. You can trigger the loading of the file by a timer or any other event in the page. As far as I'm aware, you cannot re-load it when it changes, since there's no notification from the OS - you have to use a button, timer, element event or whatever. Basically, you have to poll for changes.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
// uncomment this line for on-demand loading.
byId('loadBtn').addEventListener('click', onLoadBtnClick, false);
}
// fileVar is an object as returned by <input type='file'>
// tgtElem is an <iframe> or <img> element - can be on/off screen (doesn't need to be added to the DOM)
function loadFromFile(fileVar, tgtElem)
{
var fileReader = new FileReader();
fileReader.onload = onFileLoaded;
fileReader.readAsBinaryString(fileVar);
function onFileLoaded(fileLoadedEvent)
{
var result,data;
data = fileLoadedEvent.target.result;
result = "data:";
result += fileVar.type;
result += ";base64,";
result += btoa(data);
tgtElem.src = result;
}
}
function onLoadBtnClick(evt)
{
var fileInput = byId('mFileInput');
if (fileInput.files.length != 0)
{
var tgtElem = byId('tgt');
var curFile = fileInput.files[0];
loadFromFile(curFile, tgtElem);
}
}
</script>
<style>
</style>
</head>
<body>
<button id='loadBtn'>Load</button><input id='mFileInput' type='file'/><br>
<iframe id='tgt'></iframe>
</body>
</html>
you can use nodejs to watch for a filechange using watchfile module, if you just want to watch the filechange and its content. you can run following code using node, but it only consoles the file changed in your terminal.
var fs=require('fs');
fs.watchFile('message.text', function (curr, prev) { //listens to file change
fs.readFile('message.text', function(err,data){ //reads the file
console.log(data.toString()); //consoles the file content
});
});
On click of a button called result, I want to read and display a text file (which is present in my local drive location say: C:\test.txt) using Javascript function and display the test.txt file contents in a HTML text area.
I am new to Javascript,can anyone suggest the code for Javascript function to read and display the contents of .txt file?
An Ajax request to a local file will fail for security reasons.
Imagine a website that accesses a file on your computer like you ask, but without letting you know, and sends the content to a hacker. You would not want that, and browser makers took care of that to protect your security!
To read the content of a file located on your hard drive, you would need to have a <input type="file"> and let the user select the file himself. You don't need to upload it. You can do it this way :
<input type="file" onchange="onFileSelected(event)">
<textarea id="result"></textarea>
function onFileSelected(event) {
var selectedFile = event.target.files[0];
var reader = new FileReader();
var result = document.getElementById("result");
reader.onload = function(event) {
result.innerHTML = event.target.result;
};
reader.readAsText(selectedFile);
}
JS Fiddle
Using $.ajax() function: http://api.jquery.com/jQuery.ajax/
$(function(){
$.ajax({
url: "pathToYourFile",
async: false, // asynchronous request? (synchronous requests are discouraged...)
cache: false, // with this, you can force the browser to not make cache of the retrieved data
dataType: "text", // jQuery will infer this, but you can set explicitly
success: function( data, textStatus, jqXHR ) {
var resourceContent = data; // can be a global variable too...
// process the content...
}
});
});
As You've mentionned HTML, I assume you want to do this in a browser; Well the only way to access a local file in a browser is by using the File API, and the file can only be obtained via a user's manipulation such selecting a file in an <input type='file'> element, or drag&dropping a file in your page.
We could achieve this by, I should say, creating a virtual file!
Storing the contents of the text file into a Javascript string variable. However, one should consider all new lines and other special symbols\characters and etc.!
We than can markup a script tag in our HTML to load that *.js Javascript like this:
<script src="my_virtual_file.js"></script>
The only difference here is that a text file that could contain:
Goodnight moon
Follow the white rabbit
In a Javascript script string variable should look like this:
var my_virtual_file = "Goodnight moon\nFollow the white rabbit";
Later on, you can access this variable and treat it as you wish...
A programming language like Javascript that follows standards like ECMAScript, gives you a wide range of capabilities to treat and convert data from one type into another.
Once you have your Javascript script loaded, you can then access that variable by any button in your HTML by assigning a function call on its onclick attribute like this:
<button onclick="MyVirtualFile()"></button>
And ofcourse, you just add a script tag to your HTML, like this:
<script>
functiion MyVirtualFile(){
alert(my_virtual_file);
};
</script>
... or your may just create and import another Javascript script containing that same function, under your desire.
If you are concerned about how much information you can store into a Javascript string variable, just take a look at this interesting (and old as this one :D) SO thread.
Lets see if this snippet works :):
var my_virtual_file = "Goodnight moon\nFollow the white rabbit"
function MyVirtualFile(){
alert(my_virtual_file);
// Do anything else with your virtual file
};
<!DOCTYPE html>
<html>
<head>
<script src="my_virtual_file.js">
</script>
</head>
<body>
<h1>HTML Javascript virtual file</h1>
<button onclick="MyVirtualFile()">Alert my_virtual_file</button>
</body>
</html>
You can programatically access and dynamically change the contents of your Javascript script, but you should remind that you need to reload your HTML so the browser can load the new contents.
On your filesystem, you can just treat this *.js as a *.txt file, and just change its contents keeping in mind the Javacript.