Looping through Photoshop layers in Javascript - javascript

I'm trying to write a Photoshop script that will show all layers of a given name. I need to loop through all the possible nested layer sets and am using the following code:
function showBounds(layerNode)
{
for(var layer in layerNode.artLayers)
{
if (layer.name == "#bounds")
{
layer.visible = 1;
}
}
showBounds(layerNode.layerSets);
}
showBounds(app.activeDocument.doc.layerSets);
But when I run it, I get the following error:
Error 1302: No such element
Line: 5
-> for(var layer in layerNode.artLayers)
artLayers should be a property of LayerSets, so I'm confused.
This is also my first attempt at scripting PS (and using javascript), so there might be some fundamental concept I am not getting.

I think you need something more like:
function showBounds(layerNode) {
for (var i=0; i<layerNode.length; i++) {
showBounds(layerNode[i].layerSets);
for(var layerIndex=0; layerIndex < layerNode[i].artLayers.length; layerIndex++) {
var layer=layerNode[i].artLayers[layerIndex];
if (layer.name == "#bounds") {
layer.visible = 1;
}
}
}
}
showBounds(app.activeDocument.layerSets);
Also, javascripts for...in syntax doesn't work the way you think it does. It's not like a foreach loop. It loops over the property names of an object.

Related

Looping data in javascript

How can I get the value BrandName in this image using javascript loop.
UPDATED: Since data variable you use to display the response is already a CartObject then use:
for (var i = 0, len = data.CartLists.length; i < len; i++) {
console.log( data.CartLists[i].Item.BrandName );
}
An alternative to the one VisioN said is the following:
for (var CartItemId in CartObject.CartLists) {
Console.log(CartObject.CartLists[CartItemId].Item.BrandName);
}
However, If you would attach an Prototype to the JSON object, you could obtain an Object in the for-loop instead of an Integer (Number).
for (var CartItem in CartObject.CarLists) {
Console.log(CartItem.Item.BrandName);
}
Note that if you are going to make everything right, you should insert the following in the for-loop:
if (CartObject.CarLists.hasOwnProperty(CartItem)) {
Console.log(CartItem.Item.BrandName);
}
This example will work, but as seen in the comments below. The use of it is not what it is designed for. The For-In loop is designed to loop over Object properties, not Array items.

Get CSSKeyframesRule length

I'm iterating through a CSS keyframe in order to change the original to a new animation based on the keyframe that is closest the current behavior of the element being animated. I use the function below to obtain the keyframe rules by iterating through the stylesheets.
function findKeyframesRule(rule) {
var ss = document.styleSheets;
for (var i = 0; i < ss.length; ++i) {
for (var j = 0; j < ss[i].cssRules.length; ++j) {
if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE
&& ss[i].cssRules[j].name == rule) {
return ss[i].cssRules[j];
}
}
}
return null;
}
called like so: var keyframes = findKeyframesRule(anim);
My Problem: I need to get the length/size of ss[i].cssRules[j] (or the variable keyframes because they point to the same WebkitCSSKeyframesRule object) but have been unable to find a way to do so. I found what I think is the source for CSSKeyframesRules here, but it is in C, so I am unable to use the methods they use to find the length/size, i.e. ::length and such.
I know it has a length because I can call things like keyframes[3].keyText and get a value, so it acts like an array.
I have tried keyframes.size(), keyframes.forEach, keyframes.length, and some more attempts but they don't work because it's not an array, it's a CSSKeyframesRule object. I also attempted work arounds using the ¿parent? (I don't what to call it - I mean ss, ss[i], and ss[i].cssRules) including ss[i].cssRules.length which I thought would work but it doesn't.
Here is a fiddle to show my problem
Do any of you have any ideas?
Your code is working fine. Just try to alert
keyframes.cssRules.length
will get 5
alert(keyframes.cssRules.length);
Fiddle: http://jsfiddle.net/creativevilla/T83Nc/

Mootools is adding unwanted function calls to JSON results

I have a function that gets a list of vehicles in an asp.net page
function GetVehicleCounts(totalVehicles, vehiclesInDepot, vehiclesInFilter, vehiclesInKnownLocations, vehiclesInUnknownLocations, vehiclesNotInDepot)
{
vehiclesInDepot.value = 0;
vehiclesInFilter.value = 0;
vehiclesInKnownLocations.value = 0;
vehiclesInUnknownLocations.value = 0;
vehiclesNotInDepot.value = 0;
var listofVehicles;
var count = 0;
for (var k in vehicles_dm) {
vehiclesInDepot.value++;
if (vehicles_dm[k].IsInFilter) {
vehiclesInFilter.value++;
}
if (vehicles_dm[k].CurrentFeatureType == 11) {
vehiclesInUnknownLocations.value++;
}
else {
vehiclesInKnownLocations.value++;
}
}
if (vehicles_dm != null) {
vehiclesNotInDepot.value = totalVehicles - vehicles_dm.length;
}
}
However, when I add Mootools to the page I run into the problem of Mootools adding all the function calls to the results. This ends up getting repeated for any function that is similar. Any ideas for correcting?
I don't have a choice about using Mootools and the existing page is done in jQuery.
I found the answer!
'for..in is not meant for array iteration. It iterates over all the properties of an object that are not built-in. Since MooTools has added more functions to Array prototype, they are now array properties as well. See this https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Statements/For...in
Just use a basic for loop for array iteration.'
Javascript array iteration using for..in with MooTools included

JS in indesign. autotag error

I'm trying to apply tags to all the EPS files in the document.
My code:
#target indesign
var allItems=app.activeDocument.pageItems.everyItem().getElements().slice(0);
for(var i=0;i<allItems.length;i++)
{
var allInnerItems = allItems[i].allPageItems;
for(var j=0;j<allInnerItems.length;i++)
{
(allInnerItems[j].toString() == "[object EPS]") ?
allInnerItems[j].parent.autoTag() : alert('false');
}
}
The code finds all EPS and applies to their Rectangle objects AutoTag method. But I was given the error: "The object or the parent story is already tagged or cannot be taged". Besides if i choose some rectangle object with EPS and click the function "AutoTag" in user interface, it will work.
Maybe somebody knows, what should I do?
Thanks in advance!
I think this should work for what you are trying to do.
In the inner loop you forgot to change i++ to j++.
Also, you don't have to get the string value of an object to test against it (ie. .toString() == "[object EPS]"), you can just ask for its constructor.
Finally, if you don't want any more errors for elements that are already tagged, you can add a condition to your if statement that tests whether or not the pageItem has an associatedXMLElement before attempting to autoTag() it.
var allItems = app.activeDocument.pageItems.everyItem().getElements();
for(var i=0; i<allItems.length; i++)
{
var allInnerItems = allItems[i].allPageItems;
for(var j=0;j<allInnerItems.length; j++)
{
var item = allInnerItems[j];
if (item.constructor == EPS && !item.parent.associatedXMLElement) {
item.parent.autoTag()
} else {
alert('false');
}
}
}

Can't call public method while looping over object array

I'm starting to play around a bit with OOP in JavaScript and I have an array of simple objects that I'm trying to loop over and call a method on each, however, when I run this under Google Chrome, I get the following exception in the JavaScript debugger:
Uncaught TypeError: Object 0 has no method 'drawHisto'
Simplified code snippet below:
var histograms = [];
var h1 = null;
var h2 = null;
var h3 = null;
function Init() {
h1 = new Histogram(canvas1, "red");
h2 = new Histogram(canvas2, "blue");
h3 = new Histogram(canvas3, "green");
histograms = [ h1, h2, h3];
}
function Histogram(canvas, color) {
// this is my constructor
}
Histogram.prototype.drawHisto = function() {
// I will add code here to draw the histogram
}
function DrawHistograms() {
for (var h in histograms) {
h.drawHisto(); // Throws exception!
}
// h1.drawHisto() <--- this works
}
Any idea what I might be doing wrong? I've simplified the code here a bit, so if you find that the problem must be elsewhere, I can add additional context.
Thank you.
A for in loop in JavaScript does not iterate over an array's values, but rather over an object's keys. Simply use a for loop as usual:
function DrawHistograms() {
for (var i = 0; i < histograms.length; i++) {
histograms[i].drawHisto();
}
}
Or, if compatibility with Internet Explorer 8 and earlier is no issue, you may be able to use Array.forEach:
function DrawHistograms() {
histograms.forEach(function(h) {
h.drawHisto();
});
}
for (var h in histograms) {
histograms[h].drawHisto();
}
The for-in-loop in Javascript can be surprising at first: it doesn't loop over the values of the array, but rather the keys. For a straight-up array, I tend to prefer the more verbose but clearer standard for-loop:
for (var i = 0; i < histograms.length; i++) {
histograms[i].drawHisto();
}
Fun fact time! The for-in-loop can be handy for iterating over key-value mappings like {foo: 'bar', spam: 'eggs'}, but beware: it'll iterate over inherited keys, as well. For example, if some wiseguy decided to declare Object.prototype.myMethod, you'd see the keys foo, spam, and myMethod appear. The hasOwnProperty method can make the loop safe, though:
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
// proceed with confidence
}
}

Categories