Sunday, May 28, 2006
Working with Heights and Widths
One of the frustrations of InDesign's object model is that you can't work directly with the height and width of most items (tables are an exception). PageItems, in all their flavors, come with geometricBounds (and visibleBounds, but I've seldom been moved to use that property).
Often, when working with geometry, you want to know the height or width of an object, so you'll often find yourself doing something like:
Well, there's more than one problem here:
I confess that I don't know how to let you just write this very simple statement, but I can very easily get you a whole lot closer. Just add this method definition to your script:
However, setting the height (or width) is something that has come up fairly often, and I've usually done that with code that clutters up my mainline scripts, making them harder to read when I need to come back to them.
It is perhaps worth a moment or two to discuss the merits of having a single height method (which returns the height if no argument is provided, but which sets the height if the first argument is a number). Perhaps having two methods: getHeight() and setHeight(ht) would be a better solution. I think this is a personal choice. In my case, I'd prefer to have just the single method. So, that's how I'll spend this Sunday morning of a holiday weekend, writing the methods height(ht) and width(wd) to return the appropriate values if the argument is missing, but to set them if present.
Often, when working with geometry, you want to know the height or width of an object, so you'll often find yourself doing something like:
myBds = myPI.geometricBounds;where myPI is a reference to some PageItem.
myHeight = myBds[2] - myBds[0];
Well, there's more than one problem here:
- The height of an object ought to take into consideration its rotation. Geometric bounds gives you the coordinates (top, left, bottom, right -- don't forget that bottom is lower on the page and therefore has a larger y value because of the way that InDesign's coordinate system works) of the bounding box, so the height returned here is the height consumed by the item's current position on the page and not its real height.
- It takes up two lines of code (more if we solve the rotation problem) when really all you wanted to do was:
myHeight = myPI.height;
I confess that I don't know how to let you just write this very simple statement, but I can very easily get you a whole lot closer. Just add this method definition to your script:
Object.prototype.height = function() {and you can now get the height by simply writing:
var bds = this.geometricBounds;
return bds[2] - bds[0];
}
myHeight = myPI.height();While remembering to include the parentheses is a tad irksome, we can put to use the fact that this is a call to a method.
- If we want to solve the rotation problem, we can do so in the method, so the calling code's purpose remains clear and easy to read.
- We can extend the method to accept a parameter which would set rather than get the height.
However, setting the height (or width) is something that has come up fairly often, and I've usually done that with code that clutters up my mainline scripts, making them harder to read when I need to come back to them.
It is perhaps worth a moment or two to discuss the merits of having a single height method (which returns the height if no argument is provided, but which sets the height if the first argument is a number). Perhaps having two methods: getHeight() and setHeight(ht) would be a better solution. I think this is a personal choice. In my case, I'd prefer to have just the single method. So, that's how I'll spend this Sunday morning of a holiday weekend, writing the methods height(ht) and width(wd) to return the appropriate values if the argument is missing, but to set them if present.