femkeblanco
Guide
femkeblanco
Guide
Activity
‎May 02, 2024
05:27 AM
1 Upvote
Unnamed items are an empty string (""), not undefined.
... View more
‎May 01, 2024
01:10 PM
No criticism intended. And you are probably right that it may still be more efficient to ask in this forum.
I just wanted to indicate that you will have to provide uber-precise instructions to so-called intelligent devices like ChatGPT in order to get some well-oiled scripting approaches.
... View more
‎Apr 30, 2024
01:34 PM
!! Awesome! That works great! Thank you so much. This will save me time as this is a often repeated step in a production path for fabric panels I deal with all day =] One last thing... I noticed that the second object, after being rotated, does not show a rotation value in the properties panel. I usually use this to set the rotation back to zero after applying some other processes to that object. Any idea how to apply the rotation so that it shows as a property?
... View more
‎Apr 14, 2024
06:21 PM
1 Upvote
Thank You !
... View more
‎Apr 14, 2024
02:53 PM
1 Upvote
@femkeblanco don't pretend you're not one of us too! Haha 😜
... View more
‎Apr 07, 2024
03:12 PM
Hi @Razamus, I had this problem too. There was a bug in VSCode that caused it to run in ARM mode whenever it had restarted after an update (which was fairly frequent).
I solved it be reinstalling the Intel-specific build of VSCode (not universal). In this case there is no way it can switch to the ARM binaries. You can choose this option at the VSCode download page.
(By the way, I also run a copy of ARM-only "VSCode Insiders". I use this for non-ExtendScript stuff. I choose insiders because it has its own bundle id which means we can pair different file types to launch whichever version you like—which you can't do if you have multiple copies of plain VSCode installed).
- Mark
... View more
‎Apr 02, 2024
05:41 PM
how to open pdf that is contains multiple page , and without prompt of select page?
... View more
‎Mar 31, 2024
04:43 PM
1 Upvote
Thank you so much! You really helped me! 🙂
... View more
‎Mar 01, 2024
01:01 PM
Bonjour, C'est pourtant simple: Sélectionnez les objets Touche de raccourci <o> 1 Clic sur un des points situés sur l’axe de symétrie par exemple le point C (si vous avez tracé un axe de symétrie clic sur l"axe). 2 Faire glisser vers la droite <MAJ>+<ALT> Ou encore plus simple: Clic sur le point C appuyez sur <ALT> et clic sur un deuxième point D. Même méthode si l'axe est incliné. Avec un axe clic à deux endroits sur l'axe (1 <ALT> puis 2) Remarque: l'axe n'appartient pas à la sélection, cela peut être un segment d'un tout autre objet.
... View more
‎Feb 29, 2024
04:11 PM
1 Upvote
Okay, I've brought a bigger gun this time—my `getItems` function—and sorry it's a long script—it has evolved over many years. I've just modified to also collect Layers so hopefully I didn't introduce any bugs.
I've configured the script below to apply the titleCase to every unlocked, visible page item and layer in the document. I'm interested how it goes with your complex-document, so please let me know. (I'd also like to know if it still crashed even if you set getLockedItems and getHiddenItems both to true.)
- Mark
/**
* Page item and layer names to title case.
* NOTE: sometimes you must refresh the layers panel to see the changes.
* @author m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/can-someone-share-script-that-changes-figure-name-inside-layer-from-quot-all-caps-quot-to-quot-small/m-p/14453811
*/
(function () {
var counter = 0;
// I'm using my `getItems` function just as
// an engine for applying the titleCase to
// every visible, unlocked page item and layer
getItems({
from: app.activeDocument,
getLayers: true,
getGroupItems: true,
getLockedItems: false,
getHiddenItems: false,
filter: function (item) {
if (item.name) {
item.name = titleCase(item.name);
counter++;
}
return false;
},
});
app.redraw();
alert('Examined ' + counter + ' items.');
})();
/**
* Formats string as title case.
* @Param {String} str
* @Returns {String}
*/
function titleCase(str) {
return str
.toLowerCase()
.replace(/\b\w/g, function (ch) {
return ch.toUpperCase();
});
};
/** ------------------------------------------------------------------- *
* GET ITEMS *
* -------------------------------------------------------------------- *
* @author m1b *
* @version 2024-03-01 *
* -------------------------------------------------------------------- *
* Collects page items from a `from` source, eg. a Document, Layer, *
* GroupItem, or Array. Will look inside group items up to `maxDepth`. *
* Search can be filtered using `filter` function. Note that the *
* filter function is evaluated last in the filtering process. *
* -------------------------------------------------------------------- *
* Example 1. Get all items in document: *
* *
* var myItems = getItems({ from: app.activeDocument }); *
* *
* -------------------------------------------------------------------- *
* Example 2. Get all selected items except groups: *
* *
* var myItems = getItems({ *
* from: app.activeDocument.selection, *
* getGroupItems: false, *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 3. Using `filter` function to choose item type: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: function (item) { *
* return ( *
* 'PathItem' === item.typename *
* || 'CompoundPathItem' === item.typename *
* ); *
* } *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 4. Using `filter` function: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: onlyPngLinks *
* }); *
* *
* function onlyPngLinks(item, depth) { *
* return ( *
* 'PlacedItem' === item.typename *
* && '.png' === item.file.name.slice(-4).toLowerCase() *
* ); *
* }; *
* *
* -------------------------------------------------------------------- *
* Example 4. Using the `filter` function for custom collecting: *
* *
* This example bypasses the normal returned array and instead *
* captures items in an "external" array `itemsByDepth`. *
* *
* var itemsByDepth = []; *
* *
* function getItemsByDepth(item, depth) { *
* if (undefined == itemsByDepth[depth]) *
* itemsByDepth[depth] = []; *
* itemsByDepth[depth].push(item); *
* }; *
* *
* getItems({ *
* from: app.activeDocument, *
* filter: getItemsByDepth *
* }); *
* *
* -------------------------------------------------------------------- *
* @Param {Object} options - parameters
* @Param {PageItem|Array<PageItem>|Document|Layer} options.from - the thing(s) to look in, eg. a selection.
* @Param {Function} [options.filter] - function that, given a found item, must return true (default: no filtering).
* @Param {Boolean} [options.getPageItems] - whether to include page items in returned items (default: true).
* @Param {Boolean} [options.getGroupItems] - whether to include GroupItems in returned items (default: true).
* @Param {Boolean} [options.getLayers] - whether to include Layers in returned items (default: false).
* @Param {Boolean} [options.getHiddenItems] - whether to include hidden items in returned items (default: true).
* @Param {Boolean} [options.getLockedItems] - whether to include locked items in returned items (default: true).
* @Param {Boolean} [options.getGuideItems] - whether to include guide items in returned items (default: false).
* @Param {Number} [options.maxDepth] - deepest folder level (recursion depth limit) (default: 99).
* @Param {Boolean} [options.returnFirstMatch] - whether to return only the first found item (default: false).
* @Param {Number} [depth] - the current depth (private).
* @Returns {Array|PageItem} - all the found items in a flat array, or the first found item if `returnFirstMatch`.
*/
function getItems(options, depth) {
// defaults
options = options || {};
var found = [],
depth = depth || 0,
items = options.from;
if (!options.initialized)
// once-off initialization
if (!initialize())
return [];
itemsLoop:
for (var i = 0, item, len = items.length; i < len; i++) {
item = items[i];
if (
false === excludeFilter(item)
&& true === includeFilter(item)
) {
// item found!
found.push(item);
if (options.returnFirstMatch)
break itemsLoop;
}
if (
'GroupItem' !== item.constructor.name
&& 'Layer' !== item.typename
)
// only items with children from here
continue itemsLoop;
if (
excludeHidden(item)
|| excludeLocked(item)
)
// don't look into excluded containers
continue itemsLoop;
if (depth >= options.maxDepth)
// don't go deeper
continue itemsLoop;
// set up for the next depth
options.from = item.pageItems;
// look inside
found = found.concat(getItems(options, depth + 1));
}
// this level done
if (true == options.returnFirstMatch)
return found[0];
else
return found;
/**
* Returns true when the item should be not be found.
* @Param {PageItem|Layer} item
* @Returns {Boolean}
*/
function excludeFilter(item) {
return (
isAlreadyFound(item)
// is hidden
|| excludeHidden(item)
// is locked
|| excludeLocked(item)
// is guide
|| (
false === options.getGuideItems
&& true === item.guides
)
// is layer
|| (
false === options.getLayers
&& 'Layer' === item.typename
)
// is group item
|| (
false === options.getGroupItems
&& 'GroupItem' === item.typename
)
// is page item
|| (
false === options.getPageItems
&& 'GroupItem' !== item.typename
&& undefined != item.uuid
)
);
};
/**
* Returns true when the item should be included.
* @Param {PageItem|Layer} item
* @Returns {Boolean}
*/
function includeFilter(item) {
return (
undefined == options.filter
|| options.filter(item, depth)
);
};
/**
* Returns true when the item should
* be excluded because it is hidden.
* @Param {PageItem|Layer} item
* @Returns {Boolean}
*/
function excludeHidden(item) {
return (
false === options.getHiddenItems
&& (
true === item.hidden
|| false === item.visible
)
);
};
/**
* Returns true when the item should
* be excluded because it is locked.
* @Param {PageItem|Layer} item
* @Returns {Boolean}
*/
function excludeLocked(item) {
return (
false === options.getLockedItems
&& true === item.locked
);
};
/**
* Returns true if item was already
* found, and marks item as found,
* to avoid finding same item twice.
* @Param {PageItem|Layer} item
* @Returns {Boolean}
*/
function isAlreadyFound(item) {
var uuid = item.hasOwnProperty('uuid')
? item.uuid
: item.typename + item.zOrderPosition,
isFound = !!options.isFound[uuid];
options.isFound[uuid] = true;
return isFound;
}
/**
* Returns the initialised `options` object.
* @Returns {Object}
*/
function initialize() {
// make a new object, so we don't pollute the original
options = {
initialized: true,
depth: 0,
isFound: {},
filter: options.filter,
getPageItems: false !== options.getPageItems,
getGroupItems: false !== options.getGroupItems,
getLayers: true === options.getLayers,
getHiddenItems: false !== options.getHiddenItems,
getLockedItems: false !== options.getLockedItems,
getGuideItems: true === options.getGuideItems,
maxDepth: options.maxDepth,
returnFirstMatch: options.returnFirstMatch,
};
if (
undefined == options.maxDepth
|| !options.maxDepth instanceof Number
)
options.maxDepth = 99;
// items is a single layer
if ('Layer' === items.typename)
items = [items];
// items is a document
else if ('Document' === items.constructor.name) {
var layers = items.layers;
items = [];
for (var i = 0; i < layers.length; i++)
items.push(layers[i]);
}
else if ('Array' !== items.constructor.name)
items = [items];
return items.length > 0;
};
};
... View more
‎Feb 28, 2024
10:24 AM
Thank you! I'll check them ! It took me so much precious time to prepare something for my kiddos.Tons of 💕
... View more
‎Feb 28, 2024
12:40 AM
I already had the main part (the part that draws the tiling) from before, so I felt close to the end result. But there was no applicable logic to generate the colors; most of the time was spent inputting the colors by hand. It took just over an hour.
... View more
‎Feb 26, 2024
02:44 PM
Bonjour René! Ouais, cela semble fonctionner dans les deux cas, mais je l'ai modifié par ce que vous avez suggéré, merci beaucoup!
... View more
‎Feb 25, 2024
12:04 PM
Check the script that was referred in Femkeblancos post
... View more
‎Feb 22, 2024
12:46 PM
As far as I know, the latest JavaScript reference is the 2021 one (which is in @CarlosCanto's second link), which is not that different from the ones before it, going all the way back to 2013.
... View more
‎Feb 21, 2024
10:10 PM
You just need to be in an artboard selection mode, not the normal selector(V) mode. Select the Artboard Tool then run the script and you will be good to go. You welcome.
... View more
‎Feb 18, 2024
01:25 PM
Without a runnable snippet of code and the file causing the error, your chances of an answer are slim.
... View more
‎Feb 16, 2024
01:01 AM
Hi Femkeblanco, It is working. Thanks for your help.
... View more
‎Feb 14, 2024
03:43 PM
1 Upvote
Why would you expect anyone to help you if you're rude to the first person who tries?
... View more
‎Feb 12, 2024
07:48 AM
Works really well with all different shapes. Thank you very much for your help. Both answers are correct, just use for both could be slightly altered. Amazing job again!
... View more
‎Feb 09, 2024
07:35 PM
Good to hear! 🙂
... View more
‎Feb 06, 2024
02:10 PM
1 Upvote
"jntp" is the join type of 0 (0 round, 1 bevel and 2 miter). "mlim" is the miter limit of 4. "ofst" is the offset of 0.283 points (or 0.1 mm); this can be a negative value.
... View more
‎Feb 01, 2024
02:26 PM
2 Upvotes
I can't think of a simpler way than moving objects into group (temporarily). There is another approach, which is probably *less* simple which is to script a whole artboard export. Or a quick, png version is Document.imageCapture:.
var doc = app.activeDocument,
bounds = doc.artboards[0].artboardRect,
f = File(Folder.desktop + '/test.png'),
options = new ImageCaptureOptions();
options.antiAliasing = true;
options.resolution = 500;
options.transparency = false;
doc.imageCapture(f, bounds, options);
Then you would have to place/embed the exported image depending on what you wanted.
But, no, I think the grouping method would be simplest.
- Mark
... View more
‎Jan 29, 2024
10:37 PM
1 Upvote
U'r function works but, the first answers by RobOctopus was more easy ahah
... View more
‎Jan 29, 2024
04:07 PM
1 Upvote
Hi @tomd75724979, a few notes:
1. I often write wrappers around Illustrator objects, but the one's I make aren't anything like a "sub-class" like you might make in other environments (or that Femke described). This may say more about me than anything generally.
2. I *almost never* use any form of inheritance—it just hasn't seemed useful for my projects. Again, this may not be a general experience for people. EDIT: oops, I mean to say I don't use inheritance aside from the built-in prototypal inheritance—I use that A LOT. 🙂
3. Inheritance and hierarchy has nothing *inherently* (no pun intended!) to do with object oriented programming. I find OOP *extremely* useful and yet I almost never need inheritance.
4. As @femkeblanco discusses, using prototypes is a good tool we have to express OOP principals.
With OOP we ask question such as "what does this object (by itself) know about?" and "what does this object (by itself) know how to do?" and "what are the relationships between this object and that object". These concepts are important: "What does the class know, versus what does each instance know?" and "What can the class do, versus what can each instance do?"
- Mark
... View more
‎Jan 20, 2024
10:36 AM
You're welcome.
... View more
‎Jan 18, 2024
12:33 PM
You have saved me so much time and aggravation. Thank you stranger.
... View more
‎Jan 17, 2024
02:14 AM
Hi Charu, The template I have a text with stroke and fill text. When I run app.executeComand('Find Fill & Stoke menu item"), the app.activedocument.defaultFillColor is working for text without any stroke but not to text with stroke and fill. Can you help me on this. Thanks.
... View more
‎Jan 07, 2024
01:52 PM
2 Upvotes
to add to what femkeblanco said, those properties are called "creation properties" which are only set at creation time. Once the dialog is rendered you can read the properties but you can not change them.
... View more