I tried to keep it simple enough to be talked through and I'm sure there will always be a better way out there, but one way to do this is to iterate over the selection and stack the current object's width (or height) plus an offset to the current total. I take a few shortcuts to functions that aren't below because it's long enough, but the full working script is here.
var exist = app.documents.length > 0;
var hasSelection = app.selection.length > 0;
function alignObjects() {
if (exist && hasSelection) {
// Get the [x1, y1, x2, y2] array for the bounding box of our current selection
// x2 and y2 are not width and height, a Rect is upper left corner and bottom right corner : [minX, minY, maxX, maxY]
var fullRect = getBounds(app.selection);
// Centerpoint positions for total selection is width/2 or height/2 :
var verticalMidpoint = (fullRect[2] - fullRect[0])/2;
var horizontalMidpoint = (fullRect[3] - fullRect[1])/2;
// declare our offsets
var lastXOffset, lastYOffset;
// Rearrange order of selection from left-right or top-down, in case these were selected out of order
var selector = (/(horizontal)|x/i.test(arguments[0])) ? 'x' : 'y' ;
var selection = orderByPosition(selector);
// iterate through each item in our selection
for (var i = 0; i < selection.length; i++) {
// the current item is
var target = selection;
// declare transform properties
var xPos, yPos;
var width = target.width;
var height = target.height;
// Offset should be zero at first or when distribute isn't needed
if ((i < 1) || (arguments.length == 1)) {
lastXOffset = 0;
lastYOffset = 0;
} else {
// but calculate position by total previous width/height plus an offset number:
if (/(horizontal)|x/i.test(arguments[0])) {
// horizontal adds previous item's width plus number from function and itself (previous value)
lastXOffset = lastXOffset + selection[i-1].width + arguments[1];
} else {
// vertical adds previous height plus offset plus itself
lastYOffset = lastYOffset + selection[i-1].height + arguments[1];
}
}
// So if horizontal
if (/(horizontal)|x/i.test(arguments[0])) {
// and has two parameters (to distribute)
if (arguments.length > 1) {
// then the x position is the selection box's start/left plus the previous total width of our loop
xPos = fullRect[0] + lastXOffset;
} else {
// but if only one parameter, keep the original x position
xPos = target.geometricBounds[0];
}
// Now align -- y position is the selection box's midpoint plus half this item's height (align to it's center)
target.position = [xPos, horizontalMidpoint + (height/2)]
} else {
// otherwise if vertical and distribute
if (arguments.length > 1) {
// y position is selection box top minus total height of loop
yPos = fullRect[1] - lastYOffset;
} else {
// but if vertical and align without distribute, keep the original y
yPos = target.geometricBounds[1];
}
// Align every x position to center of selection minus half this item's width, it's own center
target.position = [verticalMidpoint - (width/2), yPos]
}
}
}
}