Recursive function Javascript concat array result - ImageJ - javascript

I try to make a javascript code for ImageJ, wich have to goal to allow me to select a directory, and return me all jpg and jpeg file in the directory and sub-directory.
I have do this code, it's work well for direct children, he call well getJpeg on subdirectories (I have verify it with some IJ.log), but the jpeg Array is not concat with result of recursives call
Have you an idea?
importClass(Packages.ij.IJ);
importClass(Packages.ij.plugin.frame.RoiManager);
importClass(Packages.ij.gui.GenericDialog);
importClass(Packages.ij.io.OpenDialog);
importClass(Packages.java.io.File);
var dirstr = IJ.getDirectory("Choose the stacks folder");
var jpeg = getJpeg(dirstr);
for (var i = 0; i < jpeg.length; i++) {
IJ.log(jpeg[i]);
}
function getJpeg(dirst) {
var dir = new java.io.File(dirst);
var names = dir.listFiles();
var jpeg = new Array();
for (var i = 0 ; i < names.length; i++) {
if(names[i].isDirectory()){
jpeg.concat(getJpeg(names[i].getPath()));
continue;
}
var namest = names[i].getName();
if (namest.match(/.*\.jpg|jpeg/)) {
var path = names[i].getPath();
jpeg.push(path);
}
}
return jpeg;
}
Thank you :)

The problem come from a missread from concat documentation ( w3schools.com/jsreF/jsref_concat_array.asp ). Have to put
jpeg = jpeg.concat(getJpeg(names[i].getPath()));

Related

Adding Multiple Arguments to a Custom Function in Google Sheets

I've searched high and wide for an answer but can't seem to find it. I am trying to alter my custom function that looks up sitemap URL's and the date they were updated to accept a range of inputs.
Here is the current function that works:
function sitemap(sitemapUrl, namespace) {
var array = [];
var xml = UrlFetchApp.fetch(sitemapUrl).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement();
var sitemapNameSpace = XmlService.getNamespace("http://www.sitemaps.org/schemas/sitemap/0.9");
var urls = root.getChildren('url', sitemapNameSpace);
for (var i = 0; i < urls.length; i++) {
var loc = urls[i].getChild('loc', sitemapNameSpace).getText();
var lastmod = urls[i].getChild('lastmod', sitemapNameSpace).getText();
array.push([loc, lastmod]);
}
return array;
}
I've tried using Google's example below but doesn't seem to work however I incorporate it into my function. Any ideas?
function DOUBLE(input) {
if (input.map) { // Test whether input is an array.
return input.map(DOUBLE); // Recurse over array if so.
} else {
return input * 2;
}
}
Edit: This is how I tried to use Google's example for my function:
function sitemaps(sitemapUrl) {
var array = [];
var xml = UrlFetchApp.fetch(sitemapUrl).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement()
var sitemapNameSpace = XmlService.getNamespace("http://www.sitemaps.org/schemas/sitemap/0.9")
var urls = root.getChildren('url', sitemapNameSpace)
for (var i = 0; i < urls.length; i++) {
var loc = urls[i].getChild('loc',sitemapNameSpace).getText();
var lastmod = urls[i].getChild('lastmod',sitemapNameSpace).getText();
array.push([loc, lastmod]);
}
if (sitemapUrl.map) {
return sitemapUrl.map(sitemaps);
} else {
return array
}
You are no using the same format as the Google example. As of right now you are checking if the input is an array after actually retrieving the data.
But you using fetch with an array as input could trigger an Error and the function may no get to the point where it checks if the sitemapUrl can be used with map.
Also take into account that map will call the function in every single element of the array and return an array with a result for each of element. So in your case B3:B6 would call the function for the value at B3, B4, B5 and B6 and return an array of length 4 with the result. For your case in which you want a single list you need to flattern the array afterwards
I would change your function to be like this:
function sitemaps(sitemapUrl) {
if (sitemapUrl.map) {
return sitemapUrl.map(sitemaps).flat();
} else {
var array = [];
var xml = UrlFetchApp.fetch(sitemapUrl).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement()
var sitemapNameSpace = XmlService.getNamespace("http://www.sitemaps.org/schemas/sitemap/0.9")
var urls = root.getChildren('url', sitemapNameSpace)
for (var i = 0; i < urls.length; i++) {
var loc = urls[i].getChild('loc', sitemapNameSpace).getText();
var lastmod = urls[i].getChild('lastmod', sitemapNameSpace).getText();
array.push([loc, lastmod]);
}
return array
}
}
Although what you are doing is fine take into account that it also exists a way to retrieve all the request at the same time (
UrlFetchApp.fetch()) but for this specific case you would need to flatten a reshape the input array.

Adobe PDF Javascript to Extract Name, save file

Looking for some help with Javascript in Adobe Acrobat Pro XI.
Here's what I have so far:
/* Extract pages to file */
// Regular expression used to acquire the base name of file
var re = /\.pdf$/i;
// filename is the base name of the file Acrobat is working on
var filename = this.documentFileName.replace(re,"");
try {for (var i = 0; i < this.numPages; i+=4)
this.extractPages({
nStart: i,
nEnd: i+3,
});
} catch (e) { console.println("Aborted: " + e) }
What happens now is that it extracts the page range and creates a series of open files that I can then rename.
What I'd like to do is add a loop to extract a name from the bill, then use that as the file name to create a new file in a folder.
I found this:
for (var p = 0; p < this.numPages; p++) {
// iterate over all words
for (var n = 0; n < this.getPageNumWords(p); n++) {
if (this.getPageNthWord(p, n) == stringToSearchFor) {
pageArray.push(p);
break;
}
}
}
which I think will get me part of the way there, but I'm not sure how to include that in my loop.
I think I need to search the document a static string (in this case "Student Name") and then return the next two words.
Worked up a file to do this sort of thing using copy-pasted code (and some help from Thom Parker on the Adobe Forums, see: https://community.adobe.com/t5/acrobat/step-by-step-instructions-for-saving-a-pdf-in-acrobat-dc-using-a-javascript/m-p/10893916?page=1#M238905)
// https://community.adobe.com/t5/acrobat/how-to-set-up-a-default-value-in-execdialog/td-p/9343585?page=1
var dialogTitle = "Please specify ";
var defaultAnswer = "";
var stringToSearchFor = app.response("Client ID",
dialogTitle, defaultAnswer);
//https://acrobatusers.com/tutorials/print/how-save-pdf-acrobat-javascript/
/* Put script title here */
// Iterates over all pages and find a given string and extracts all
// pages on which that string is found to a new file.
var pageArray = [];
//var stringToSearchFor = "64718";
for (var p = 0; p < this.numPages; p++) {
// iterate over all words
for (var n = 0; n < this.getPageNumWords(p); n++) {
if (this.getPageNthWord(p, n) == stringToSearchFor) {
pageArray.push(p);
break;
}
}
}
if (pageArray.length > 0) {
// extract all pages that contain the string into a new document
var d = app.newDoc(); // this will add a blank page - we need to remove that once we are done
for (var n = 0; n < pageArray.length; n++) {
d.insertPages( {
nPage: d.numPages-1,
cPath: this.path,
nStart: pageArray[n],
nEnd: pageArray[n],
} );
}
// remove the first page
d.deletePages(0);
// https://community.adobe.com/t5/acrobat/how-to-save-as-pdf-form-using-script/td-p/9848947?page=1
// Split Path into an array so it is easy to work with
var aMyPath = this.path.split("/");
// Remove old file name
aMyPath.pop();
// Add new file name
aMyPath.push(stringToSearchFor);
// Put path back together and save
d.saveAs(aMyPath.join("/")+".pdf");
}

javascript bzip2 stream as Uint8Array

From a previous answer on Stackoverflow I found the bzip2 lib for javascript: https://github.com/antimatter15/bzip2.js
It does pretty much what I need, except that I need the output as a Uint8Array instead of a string.
I use this function from the bzip2 lib:
bzip2.simple = function(bits){
var size = bzip2.header(bits);
var all = '', chunk = '';
do{
all += chunk;
chunk = bzip2.decompress(bits, size);
}while(chunk != -1);
return all;
}
I found a way of transforming the string output into a Uint8Array :
function str2ab(str)
{
var buf = new ArrayBuffer(str.length);
var bufView = new Uint8Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
};
But for speed reasons I was hoping there was a good way to re-write the original bzip2 function so it directly outputs as a Uint8Array.
One of the main problems I’m having is that I don’t know how to dynamically increase the array.

Javascript: Uint16Array(length) returns Invalid argument

I'm trying to read a file in order to perform certain actions on the binary data before sending it to a server.
At a certain point I'm trying to convert the data returned by FileReader.readAsArrayBuffer() to an Uint16Array(). However upon doing so the code allocating the array fails with: 'Error: invalid arguments'. I need the data to be a hex string representing the entire binary.
This is the code I'm using:
function HexToHexString(ByteBuffer)
{
//Similar constructs like: 'var Array = new Uint16Array(ByteBuffer);' also fail
var View = new DataView(ByteBuffer);
var Array = new Uint16Array((ByteBuffer.byteLength / 2)); // <- this line fails
for(var i = 0; i < Array.length; i++)
{
Array[i] = View.getUint16(i*2);
}
return String.fromCharCode.apply(null, Array);
}
function OnReadFileCompletion(FileReadEvent)
{
if(FileReadEvent.target.readyState == FileReader.DONE)
{
// Debug code, will be replaced:
document.getElementById('byte_content').textContent = HexToHexString(FileReadEvent.target.result);
//FileReadEvent.target.result;
}
}
function ReadFile(File, ResultFunction)
{
var Reader = new FileReader();
Reader.onloadend = ResultFunction;
Reader.readAsArrayBuffer(File.slice(0, File.size - 1));
}
File Is a file object, ResultFunction is OnReadFileCompletion(), ByteBuffer is an '[object ArrayBuffer]'.
When I output the size of the ArrayBuffer it matches the size of the file (82kb). I'm on firefox 32 with no plugins installed.
I'm not a javascript programmer, does anyone know what I'm doing wrong?
Edit1:
It appears to have something to-do with the size of the file I'm trying to read, using a 1kb text file appears to work while a 82kb binary file does not.
Edit2
I spoke too soon, perhaps it has something to do with file types. An image file of 200kb works, while an executable of 82 does not.
It appears that javascript does not allow executable files to be accesed this way, does anybody know of any way where I could possibly access the data in hex form?
try using .length instead of byteLength
I've hacked together code that works for me, I don't know why this works or what I did wrong the other time. But it works.
function ApplyPadding(Number, PaddingLength)
{
var s = Number + "";
while (s.length < PaddingLength)
s = "0" + s;
return s;
}
function HexToHexString(ByteBuffers)
{
var AnArray = new Uint8Array(ByteBuffers);
var Result = "";
for(var i = 0; i < AnArray.length; i++)
{
if(i%2==0)
Result += ApplyPadding(AnArray[i].toString(16), 2);
}
return Result;
}
function HexStringToHex(aString)
{
var Buffer = new ArrayBuffer(aString.length*2); // 2 bytes for each char
var BufferView = new Uint16Array(Buffer);
for (var i = 0;i < aString.length; i++)
{
BufferView[i] = aString.charCodeAt(i);
}
return Buffer;
}
function OnReadFileCompletion(FileReadEvent)
{
if(FileReadEvent.target.readyState == FileReader.DONE)
{
//document.getElementById('byte_content').textContent =FileReadEvent.target.result;
var DataOfFile = HexStringToHex(FileReadEvent.target.result);
var FinalData = HexToHexString(DataOfFile);
document.getElementById('byte_content').textContent = FinalData;
//FileReadEvent.target.result;
}
}
function ReadFile(File, ResultFunction)
{
var Reader = new FileReader();
Reader.onloadend = ResultFunction;
Reader.readAsBinaryString(File.slice(0, File.size - 1));
}

Regexp to match file ending with Javascript

I want to get the file endings from some files in a list.
File 1
File 2
File 3
File 4
Basically, the file endning could be anything, and the string can contain more than just one ".". So I need to fetch the ending only.
I want to get a result that looks like:
mp4
ogg
mp3
jpg
Thanks.
You can get the extensions for all links in a document like this:
var endings = [];
var links = document.getElementsByTagName("a");
var matches;
for (var i = 0; i < links.length; i++) {
if (links[i].href) {
matches = links[i].href.match(/\.([^\.]+)$/);
if (matches) {
endings.push(matches[1]);
}
}
}
// the array endings contains a list of all link extensions
Here's a working version of the code: http://jsfiddle.net/jfriend00/XHKaT/
The regular expression here matches a period followed by one or more non-period characters at the end of the string. The parenthesized grouping allows us to extra just the extension without the period which accomplishes the result you outlined.
This function performs as you need without reporting duplicates and maintaining the order in which the filename extensions are discovered.
function getLinkedFileExtensions() {
var i, len=document.links.length, ext=[], exts={};
for (i=0; i<len; i++) {
var a = document.links[i];
if (a.href && a.href.match(/\.([A-Za-z0-9]{1,4})$/)) {
var x = RegExp.$1;
if (!(x in exts)) {
exts[x] = true;
ext.push(x);
}
}
}
return ext;
}
var ext = [].map.call(document.links, function (a) {
return (a.href.match(this) || [])[1] || "";
}, /\.([a-zA-Z0-9]*)$/).filter(String);
http://jsfiddle.net/hZ9cU/
You can use jQuery to:
Get all of your anchor elements.
For each element you can access the .attr("href") value which will be your address string i.e. "myfile.mp3"
Then you can split the string on "." character and add the value at tokenArray[tokenArray.length-1] to your result list.
Or for vanilla JS try:
function getExtensions(){
var allAnchorTags = document.getElementsByTagName("a");
var extensions = new Array();
for(var i = 0; i < allAnchorTags.length; i++){
var tokenArray = allAnchorTags[i].href.split(".");
extensions[i] = tokenArray[tokenArray.length-1];
}
return extensions;
}
which does the same as described in my algorithm except with vanilla JS syntax. Give it a shot
See Feedle
var ext = a.href.split(".");
ext = ext[ext.length -1];
console.log(ext);
EDIT :
var d = document.getElementsByTagName("a"),
ext, i, j;
for(i = 0, j = d.length; i<j; i++){
ext = d[i].href.split(".");
ext = ext[ext.length -1];
console.log(ext);
}

Categories