Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Script logic help please - Grid making

Contributor ,
Jul 27, 2025 Jul 27, 2025

Hello, been working on a script to make similar to InDesign grids for Illustrator. 

SmythWharf_0-1753661891756.png

 

Interface is self clear, detects the artboard you are on, you enter the parameters done. you can click the apply to all and then those settings go on all artboards. 

Then lets say you have a need for a different grid on a particlar artboard, well then you run it again, change the parameters, dont click apply to all and it should change just that artboard

previous versions i had did this, but the preview was not quite working, since fixing the preview I am now in a situation, where the guides are remove and never redrawn, and may margins layers are unlocked too

 

This is the preview of the new layout I want 

SmythWharf_2-1753662148185.png

 

And when I hit okay this is what I get - pure blank. Interestingly, if I hit the x button for the script, it just saves the new layout... when it should cancel it.. but thats a fix i need to do. 

 

SmythWharf_1-1753662054850.png

 

Anyhow, this is not what is wanted, it be drawing out the new guides and locking the layers 

rendering this result 

SmythWharf_3-1753662262014.png

 

 

I also noticed that when I run the script , and put in the new parameters when i undo twice, it actually makes the layout i want, twice as one time is to lock the layer, another time is to get back the guides... 

Anyhow, I am going round and round trying to fix this so any help would be great, 

thank you, 

Smyth 

/**
 * Illustrator Margins, Grid & Baseline Script [Mac-Ready]
 * No ES6 code—fully ExtendScript compatible. Tested on Mac.
 * Enhanced Preview: Fixed live updates on number changes with better event handling.
 * Cleanup: Removes baseline paths per artboard when increment=0, deletes layer if empty; similar for margins if no paths needed.
 * Fixed: Explicit lock handling in preview to prevent conflicts; apply if missing even if unchanged; forced re-add on single artboard apply.
 */

var settingsXMLPath = Folder.myDocuments + "/IllustratorGridSettings.xml";

// --- XML functions (unchanged) ---
function loadSettingsFromXML(xmlFilePath, abIdx, defaults) {
    function stringifyDefaults(defaultsObj) {
        var stringDefaults = {};
        for (var key in defaultsObj) {
            if (defaultsObj.hasOwnProperty(key)) {
                if (key === "BaselineInc") {
                    stringDefaults[key] = defaultsObj[key].toString() + "pt";
                } else if (key === "Columns" || key === "Rows") {
                    stringDefaults[key] = defaultsObj[key].toString();
                } else {
                    stringDefaults[key] = defaultsObj[key].toString() + "mm";
                }
            }
        }
        return stringDefaults;
    }

    var file = new File(xmlFilePath);
    if (!file.exists) return stringifyDefaults(defaults);
    
    file.open('r');
    var content = file.read();
    file.close();
    
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>');
    var found = content.match(abTag);
    
    if (found) {
        var vals = {};
        var tags = ["Top","Bottom","Left","Right","Columns","Rows","VertGutter","HorGutter","BaselineStart","BaselineInc"];
        for (var i = 0; i < tags.length; i++) {
            var tagName = tags[i];
            var tagRegex = new RegExp('<' + tagName + '>([\\s\\S]*?)<\\/' + tagName + '>');
            var tagMatch = found[1].match(tagRegex);
            
            if (tagMatch) {
                vals[tagName] = tagMatch[1];
            } else {
                if (tagName === "BaselineInc") {
                    vals[tagName] = defaults[tagName].toString() + "pt";
                } else if (tagName === "Columns" || tagName === "Rows") {
                    vals[tagName] = defaults[tagName].toString();
                } else {
                    vals[tagName] = defaults[tagName].toString() + "mm";
                }
            }
        }
        return vals;
    }
    
    return stringifyDefaults(defaults);
}

function saveSettingsToXML(xmlFilePath, abIdx, newVals) {
    var file = new File(xmlFilePath);
    var xmlContent = '';
    if (file.exists) {
        file.open('r');
        xmlContent = file.read();
        file.close();
    }
    var abTag = new RegExp('<Artboard index="' + abIdx + '">([\\s\\S]*?)<\\/Artboard>','g');
    xmlContent = xmlContent.replace(abTag, '');
    var abXML = '  <Artboard index="' + abIdx + '">\n';
    for (var key in newVals) {
        var value = newVals[key].toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        abXML += '    <' + key + '>' + value + '</' + key + '>\n';
    }
    abXML += '  </Artboard>\n';
    if (xmlContent.indexOf('<GridSettings>') === -1) {
        xmlContent = '<GridSettings>\n' + abXML + '</GridSettings>';
    } else {
        xmlContent = xmlContent.replace('</GridSettings>', abXML + '</GridSettings>');
    }
    file.open('w');
    file.write(xmlContent);
    file.close();
}

// --- Helpers (unchanged) ---
function mmToPt(mm) { return mm * 2.83465; }
function ptToMm(pt) { return pt / 2.83465; }
function makeRGB(r, g, b) {
    var color = new RGBColor();
    color.red = r; color.green = g; color.blue = b;
    return color;
}
function findLayer(doc, name) {
    for (var i = 0; i < doc.layers.length; i++) {
        if (doc.layers[i].name === name) return doc.layers[i];
    }
    return null;
}
function deleteLayerByExactName(doc, name) {
    for (var i = doc.layers.length - 1; i >= 0; i--) {
        if (doc.layers[i].name === name) {
            doc.layers[i].locked = false;
            doc.layers[i].visible = true;
            doc.layers[i].remove();
        }
    }
}
function removePathsForArtboard(layer, abIdx) {
    var abTag = " ab" + abIdx + " ";
    for (var i = layer.pathItems.length - 1; i >= 0; i--) {
        var p = layer.pathItems[i];
        if (p.note && p.note.indexOf(abTag) === 0) p.remove();
    }
}
function hasPathsForArtboard(layer, abIdx) {
    var abTag = " ab" + abIdx + " ";
    for (var i = 0; i < layer.pathItems.length; i++) {
        var p = layer.pathItems[i];
        if (p.note && p.note.indexOf(abTag) === 0) return true;
    }
    return false;
}

// --- Unit Parsing (unchanged) ---
function parseValueWithUnit(inputStr) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (!match) {
        var num = parseFloat(inputStr);
        return isNaN(num) ? NaN : mmToPt(num);
    }
    
    var value = parseFloat(match[1]);
    var unit = match[2].toLowerCase();
    
    if (isNaN(value)) return NaN;
    
    switch (unit) {
        case '':
        case 'mm':
            return mmToPt(value);
        case 'cm':
            return mmToPt(value * 10);
        case 'in':
        case 'inch':
            return value * 72;
        case 'pt':
        case 'point':
            return value;
        case 'px':
        case 'pixel':
            var doc = app.activeDocument;
            if (doc.rulerUnits == RulerUnits.Pixels) {
                return value;
            } else {
                return value * 0.75;
            }
        case 'pc':
        case 'pica':
            return value * 12;
        default:
            return mmToPt(value);
    }
}

function parseValueWithUnitPt(inputStr) {
    return parseValueWithUnit(inputStr);
}

function addDefaultUnit(inputStr, fieldType) {
    if (typeof inputStr !== 'string') {
        inputStr = String(inputStr);
    }
    
    inputStr = inputStr.replace(/\s/g, '');
    var match = inputStr.match(/^(-?\d*\.?\d+)([a-zA-Z%]*)$/);
    
    if (match && match[2] === '') {
        if (fieldType === "baseline") {
            return inputStr + "pt";
        } else if (fieldType === "number") {
            return inputStr;
        } else {
            return inputStr + "mm";
        }
    }
    
    return inputStr;
}

// --- Change Detection Functions ---
function isMarginsChanged(current, loaded) {
    return current.top !== loaded.top ||
           current.bottom !== loaded.bottom ||
           current.left !== loaded.left ||
           current.right !== loaded.right ||
           current.columns !== loaded.columns ||
           current.rows !== loaded.rows ||
           current.vertGutter !== loaded.vertGutter ||
           current.horGutter !== loaded.horGutter;
}

function isBaselineChanged(current, loaded) {
    return current.baselineStart !== loaded.baselineStart ||
           current.baselineInc !== loaded.baselineInc;
}

// --- Guide Creation (with added check to skip margin rectangle if zero) ---
function addMarginsAndColumnsToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, columns, vertGutter_pt, rows, horGutter_pt) {
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var width = right - left, height = top - bottom;
    var abTag = " ab" + abIdx + " ";
    
    // Skip if dimensions would be invalid
    if (width - left_pt - right_pt <= 0 || height - top_pt - bottom_pt <= 0) return;
    
    // Add margin rectangle if margins are non-zero
    if (top_pt > 0 || bottom_pt > 0 || left_pt > 0 || right_pt > 0) {
        var path = layer.pathItems.rectangle(top - top_pt, left + left_pt, width - left_pt - right_pt, height - top_pt - bottom_pt);
        path.stroked = true; path.strokeColor = makeRGB(224, 0, 255); path.strokeWidth = 0.1; path.filled = false; path.guides = true; path.note = abTag + "margin";
    }
    
    var gridColor = makeRGB(0, 176, 255);
    columns = Math.min(columns, 20);
    if (columns > 1) {
        var usableWidth = width - left_pt - right_pt;
        var colWidth = (usableWidth - (columns - 1) * vertGutter_pt) / columns;
        var x = left + left_pt;
        for (var c = 0; c < columns - 1; c++) {
            x += colWidth;
            var vGuide1 = layer.pathItems.add();
            vGuide1.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide1.stroked = true; vGuide1.strokeColor = gridColor; vGuide1.strokeWidth = 0.1; vGuide1.filled = false; vGuide1.guides = true; vGuide1.note = abTag + "colg";
            x += vertGutter_pt;
            var vGuide2 = layer.pathItems.add();
            vGuide2.setEntirePath([[x, top - top_pt], [x, bottom + bottom_pt]]);
            vGuide2.stroked = true; vGuide2.strokeColor = gridColor; vGuide2.strokeWidth = 0.1; vGuide2.filled = false; vGuide2.guides = true; vGuide2.note = abTag + "colg";
        }
    }
    
    rows = Math.min(rows, 20);
    if (rows > 1) {
        var usableHeight = height - top_pt - bottom_pt;
        var rowHeight = (usableHeight - (rows - 1) * horGutter_pt) / rows;
        var y = top - top_pt;
        for (var r = 0; r < rows - 1; r++) {
            y -= rowHeight;
            var hGuide1 = layer.pathItems.add();
            hGuide1.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide1.stroked = true; hGuide1.strokeColor = gridColor; hGuide1.strokeWidth = 0.1; hGuide1.filled = false; hGuide1.guides = true; hGuide1.note = abTag + "rowg";
            y -= horGutter_pt;
            var hGuide2 = layer.pathItems.add();
            hGuide2.setEntirePath([[left + left_pt, y], [right - right_pt, y]]);
            hGuide2.stroked = true; hGuide2.strokeColor = gridColor; hGuide2.strokeWidth = 0.1; hGuide2.filled = false; hGuide2.guides = true; hGuide2.note = abTag + "rowg";
        }
    }
}

function addBaselineGridToLayer(layer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt) {
    if (baselineInc_pt <= 0) return;
    
    var rect = ab.artboardRect;
    var left = rect[0], top = rect[1], right = rect[2], bottom = rect[3];
    var abTag = " ab" + abIdx + " ";
    var y0 = top - top_pt - baselineStart_pt;
    var yEnd = bottom + bottom_pt;
    var count = 0;
    // var maxLines = 50;  // Removed for full drawing; uncomment and adjust (e.g., to 200) if needed for performance
    while (y0 > yEnd /* && count < maxLines */) {
        var line = layer.pathItems.add();
        line.setEntirePath([[left + left_pt, y0], [right - right_pt, y0]]);
        line.stroked = true; line.strokeColor = makeRGB(80, 80, 80); line.strokeWidth = 0.05; line.filled = false; line.guides = true; line.note = abTag + "baseline";
        y0 -= baselineInc_pt;
        count++;
    }
}

// --- Preview Globals and Config ---
var isUndo = false;
var CFG = { is2020: parseInt(app.version) === 24 };
var lastPreviewTime = 0;

// --- UI Dialog with Fixed Live Preview ---
function showMarginsDialog() {
    if (app.documents.length === 0) { alert("Please open a document first."); return; }
    var doc = app.activeDocument;
    var abIdx = doc.artboards.getActiveArtboardIndex();
    var defaults = {
        Top:12.7, Bottom:12.7, Left:12.7, Right:12.7, Columns:2, Rows:2,
        VertGutter:4.233, HorGutter:4.233, BaselineStart:0, BaselineInc:12
    };
    var settings = loadSettingsFromXML(settingsXMLPath, abIdx, defaults);

    // Parse loaded settings for change detection (used only in OK)
    var loaded_pt = {
        top: parseValueWithUnit(settings.Top),
        bottom: parseValueWithUnit(settings.Bottom),
        left: parseValueWithUnit(settings.Left),
        right: parseValueWithUnit(settings.Right),
        columns: parseInt(settings.Columns),
        rows: parseInt(settings.Rows),
        vertGutter: parseValueWithUnit(settings.VertGutter),
        horGutter: parseValueWithUnit(settings.HorGutter),
        baselineStart: parseValueWithUnit(settings.BaselineStart),
        baselineInc: parseValueWithUnitPt(settings.BaselineInc)
    };

    var w = new Window("dialog", "Margins, Grid & Baseline (for Artboard " + (abIdx + 1) + ")");
    w.orientation = "column";
    w.alignChildren = "fill";
    w.spacing = 15;
    w.margins = 20;

    var marginPanel = w.add("panel", undefined, "Margins");
    marginPanel.orientation = "column";
    marginPanel.alignChildren = "fill";
    marginPanel.margins = 15;
    marginPanel.spacing = 10;
    
    var mRow1 = marginPanel.add("group");
    mRow1.orientation = "row";
    mRow1.alignChildren = "center";
    mRow1.spacing = 10;
    mRow1.add("statictext", undefined, "Top:").preferredSize.width = 60;
    var topInput = mRow1.add("edittext", undefined, settings.Top);
    topInput.preferredSize.width = 80;
    mRow1.add("statictext", undefined, "Left:").preferredSize.width = 60;
    var leftInput = mRow1.add("edittext", undefined, settings.Left);
    leftInput.preferredSize.width = 80;
    
    var mRow2 = marginPanel.add("group");
    mRow2.orientation = "row";
    mRow2.alignChildren = "center";
    mRow2.spacing = 10;
    mRow2.add("statictext", undefined, "Bottom:").preferredSize.width = 60;
    var bottomInput = mRow2.add("edittext", undefined, settings.Bottom);
    bottomInput.preferredSize.width = 80;
    mRow2.add("statictext", undefined, "Right:").preferredSize.width = 60;
    var rightInput = mRow2.add("edittext", undefined, settings.Right);
    rightInput.preferredSize.width = 80;

    var gridPanel = w.add("panel", undefined, "Grid");
    gridPanel.orientation = "column";
    gridPanel.alignChildren = "fill";
    gridPanel.margins = 15;
    gridPanel.spacing = 10;
    
    var gRow1 = gridPanel.add("group");
    gRow1.orientation = "row";
    gRow1.alignChildren = "center";
    gRow1.spacing = 10;
    gRow1.add("statictext", undefined, "Columns:").preferredSize.width = 80;
    var colInput = gRow1.add("edittext", undefined, settings.Columns);
    colInput.preferredSize.width = 60;
    gRow1.add("statictext", undefined, "Vertical Gutter:").preferredSize.width = 100;
    var vertGutterInput = gRow1.add("edittext", undefined, settings.VertGutter);
    vertGutterInput.preferredSize.width = 80;
    
    var gRow2 = gridPanel.add("group");
    gRow2.orientation = "row";
    gRow2.alignChildren = "center";
    gRow2.spacing = 10;
    gRow2.add("statictext", undefined, "Rows:").preferredSize.width = 80;
    var rowInput = gRow2.add("edittext", undefined, settings.Rows);
    rowInput.preferredSize.width = 60;
    gRow2.add("statictext", undefined, "Horizontal Gutter:").preferredSize.width = 100;
    var horGutterInput = gRow2.add("edittext", undefined, settings.HorGutter);
    horGutterInput.preferredSize.width = 80;

    var basePanel = w.add("panel", undefined, "Baseline Grid");
    basePanel.orientation = "row";
    basePanel.alignChildren = "center";
    basePanel.margins = 15;
    basePanel.spacing = 10;
    basePanel.add("statictext", undefined, "Start:").preferredSize.width = 80;
    var baselineStartInput = basePanel.add("edittext", undefined, settings.BaselineStart);
    baselineStartInput.preferredSize.width = 80;
    basePanel.add("statictext", undefined, "Increment:").preferredSize.width = 80;
    var baselineIncInput = basePanel.add("edittext", undefined, settings.BaselineInc);
    baselineIncInput.preferredSize.width = 80;

    var applyAllGroup = w.add("group");
    applyAllGroup.margins = [0, 10, 0, 0];
    var applyAllChk = applyAllGroup.add("checkbox", undefined, "Apply to all artboards");
    applyAllChk.value = (doc.artboards.length === 1);

    var previewGroup = w.add("group");
    previewGroup.margins = [0, 10, 0, 0];
    var isPreview = previewGroup.add("checkbox", undefined, "Preview (Active Artboard Only)");
    isPreview.helpTip = "Toggle to see changes live (undoable)";
    if (CFG.is2020) {
        isPreview.enabled = false;
        isPreview.helpTip = "Preview disabled due to Illustrator bug";
    }

    var btnGroup = w.add("group");
    btnGroup.orientation = "row";
    btnGroup.alignment = "right";
    btnGroup.spacing = 10;
    btnGroup.margins = [0, 15, 0, 0];
    var cancelBtn = btnGroup.add("button", undefined, "Cancel", { name: "cancel" });
    var okBtn = btnGroup.add("button", undefined, "OK", { name: "ok" });
    cancelBtn.preferredSize.width = 80;
    okBtn.preferredSize.width = 80;

    // Preview function (always updates, with explicit lock handling)
    function previewChanges() {
        if (CFG.is2020 || !isPreview.value) return;
        try {
            var doc = app.activeDocument;
            var abIdx = doc.artboards.getActiveArtboardIndex();
            var ab = doc.artboards[abIdx];

            var top_pt = parseValueWithUnit(topInput.text), bottom_pt = parseValueWithUnit(bottomInput.text),
                left_pt = parseValueWithUnit(leftInput.text), right_pt = parseValueWithUnit(rightInput.text),
                cols = parseInt(colInput.text), rows = parseInt(rowInput.text),
                vertGutter_pt = parseValueWithUnit(vertGutterInput.text), horGutter_pt = parseValueWithUnit(horGutterInput.text),
                baselineStart_pt = parseValueWithUnit(baselineStartInput.text), baselineInc_pt = parseValueWithUnitPt(baselineIncInput.text);

            if (isNaN(top_pt) || isNaN(bottom_pt) || isNaN(left_pt) || isNaN(right_pt) || 
                isNaN(cols) || isNaN(rows) || 
                isNaN(vertGutter_pt) || isNaN(horGutter_pt) || 
                isNaN(baselineStart_pt) || isNaN(baselineInc_pt) ||
                top_pt < 0 || bottom_pt < 0 || left_pt < 0 || right_pt < 0 ||
                cols < 0 || rows < 0 ||
                vertGutter_pt < 0 || horGutter_pt < 0 ||
                baselineInc_pt < 0) {
                return;
            }

            cols = Math.min(cols, 20);
            rows = Math.min(rows, 20);

            var check = checkGridFit(abIdx, top_pt, bottom_pt, left_pt, right_pt, cols, rows, vertGutter_pt, horGutter_pt);
            if (check.failCol) vertGutter_pt = mmToPt(defaults.VertGutter);
            if (check.failRow) horGutter_pt = mmToPt(defaults.HorGutter);

            var marginsLayer = findLayer(doc, "Margins and Columns") || doc.layers.add();
            marginsLayer.name = "Margins and Columns";
            var wasLockedMargins = marginsLayer.locked;
            marginsLayer.locked = false; marginsLayer.visible = true;

            var baselineLayer = findLayer(doc, "Baseline");
            var wasLockedBaseline = baselineLayer ? baselineLayer.locked : false;
            if (baselineLayer) baselineLayer.locked = false;

            removePathsForArtboard(marginsLayer, abIdx);
            if (baselineLayer) removePathsForArtboard(baselineLayer, abIdx);

            addMarginsAndColumnsToLayer(marginsLayer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, cols, vertGutter_pt, rows, horGutter_pt);
            if (baselineInc_pt > 0) {
                if (!baselineLayer) {
                    baselineLayer = doc.layers.add();
                    baselineLayer.name = "Baseline";
                    wasLockedBaseline = false;
                }
                baselineLayer.visible = true;
                addBaselineGridToLayer(baselineLayer, ab, abIdx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt);
            } else if (baselineLayer) {
                if (baselineLayer.pathItems.length === 0) {
                    baselineLayer.remove();
                    baselineLayer = null;
                }
            }

            if (marginsLayer.pathItems.length === 0) {
                marginsLayer.remove();
                marginsLayer = null;
            } else {
                marginsLayer.locked = wasLockedMargins;
            }

            if (baselineLayer) baselineLayer.locked = wasLockedBaseline;

            app.redraw();
            isUndo = true;
        } catch (err) {}
    }

    // Event wiring with onChanging for live updates
    function setupInputListeners(input) {
        input.onChanging = function() {
            if (isPreview.value) previewChanges();
        };
        input.onChange = previewChanges;
    }

    setupInputListeners(topInput);
    setupInputListeners(bottomInput);
    setupInputListeners(leftInput);
    setupInputListeners(rightInput);
    setupInputListeners(colInput);
    setupInputListeners(rowInput);
    setupInputListeners(vertGutterInput);
    setupInputListeners(horGutterInput);
    setupInputListeners(baselineStartInput);
    setupInputListeners(baselineIncInput);

    isPreview.onClick = function() {
        if (isPreview.value) {
            previewChanges();
        } else if (isUndo) {
            app.undo();
            app.redraw();
            isUndo = false;
        }
    };

    // Cleanup
    w.onClose = function () {
        if (isUndo) {
            app.undo();
            isUndo = false;
        }
    };

    // OK button (with manual preview cleanup and forced add if warranted)
    okBtn.onClick = function() {
        if (isPreview.value && isUndo) {
            // Manual cleanup of preview changes
            var doc = app.activeDocument;
            var abIdx = doc.artboards.getActiveArtboardIndex();
            var marginsLayer = findLayer(doc, "Margins and Columns");
            var baselineLayer = findLayer(doc, "Baseline");
            if (marginsLayer) {
                marginsLayer.locked = false;
                removePathsForArtboard(marginsLayer, abIdx);
                if (marginsLayer.pathItems.length === 0) marginsLayer.remove();
                else marginsLayer.locked = true;
            }
            if (baselineLayer) {
                baselineLayer.locked = false;
                removePathsForArtboard(baselineLayer, abIdx);
                if (baselineLayer.pathItems.length === 0) baselineLayer.remove();
                else baselineLayer.locked = true;
            }
            app.redraw();
            isUndo = false;
        }

        var top_pt = parseValueWithUnit(topInput.text), bottom_pt = parseValueWithUnit(bottomInput.text),
            left_pt = parseValueWithUnit(leftInput.text), right_pt = parseValueWithUnit(rightInput.text),
            cols = parseInt(colInput.text), rows = parseInt(rowInput.text),
            vertGutter_pt = parseValueWithUnit(vertGutterInput.text), horGutter_pt = parseValueWithUnit(horGutterInput.text),
            baselineStart_pt = parseValueWithUnit(baselineStartInput.text), baselineInc_pt = parseValueWithUnitPt(baselineIncInput.text);

        if (isNaN(top_pt) || isNaN(bottom_pt) || isNaN(left_pt) || isNaN(right_pt) || 
            isNaN(cols) || isNaN(rows) || 
            isNaN(vertGutter_pt) || isNaN(horGutter_pt) || 
            isNaN(baselineStart_pt) || isNaN(baselineInc_pt) ||
            top_pt < 0 || bottom_pt < 0 || left_pt < 0 || right_pt < 0 ||
            cols < 0 || rows < 0 ||
            vertGutter_pt < 0 || horGutter_pt < 0 ||
            baselineInc_pt < 0) {
            alert("Please enter valid (non-negative) numbers. Baseline increment can be 0 to skip baseline grid.");
            return;
        }
        
        var abIndices = [];
        if (applyAllChk.value) { for (var i = 0; i < doc.artboards.length; i++) abIndices.push(i); } else { abIndices.push(abIdx); }
        
        var vertGutterOverride = {}, horGutterOverride = {};
        var warnedCol = false, warnedRow = false;
        for (var i = 0; i < abIndices.length; i++) {
            var check = checkGridFit(abIndices[i], top_pt, bottom_pt, left_pt, right_pt, cols, rows, vertGutter_pt, horGutter_pt);
            if (check.failCol) {
                if (!warnedCol) { alert("Column/gutter combination doesn't fit on at least one artboard. Vertical gutter is reset to default."); warnedCol = true; }
                vertGutterOverride[abIndices[i]] = mmToPt(defaults.VertGutter);
            }
            if (check.failRow) {
                if (!warnedRow) { alert("Row/gutter combination doesn't fit on at least one artboard. Horizontal gutter is reset to default."); warnedRow = true; }
                horGutterOverride[abIndices[i]] = mmToPt(defaults.HorGutter);
            }
        }

        if (applyAllChk.value) {
            deleteLayerByExactName(doc, "Margins and Columns");
            deleteLayerByExactName(doc, "Baseline");
        }
        
        var marginsLayer = findLayer(doc, "Margins and Columns");
        var baselineLayer = findLayer(doc, "Baseline");

        var current_pt = {
            top: top_pt, bottom: bottom_pt, left: left_pt, right: right_pt,
            columns: cols, rows: rows, vertGutter: vertGutter_pt, horGutter: horGutter_pt,
            baselineStart: baselineStart_pt, baselineInc: baselineInc_pt
        };

        for (var k = 0; k < abIndices.length; k++) {
            var idx = abIndices[k];
            var thisVertGutter_pt = vertGutterOverride[idx] !== undefined ? vertGutterOverride[idx] : vertGutter_pt;
            var thisHorGutter_pt = horGutterOverride[idx] !== undefined ? horGutterOverride[idx] : horGutter_pt;
            var ab = doc.artboards[idx];

            // For single artboard, check if changed or missing paths; for all, always update
            var updateMargins = applyAllChk.value || isMarginsChanged(current_pt, loaded_pt) || !marginsLayer || !hasPathsForArtboard(marginsLayer, idx);
            if (updateMargins) {
                if (!marginsLayer) {
                    marginsLayer = doc.layers.add();
                    marginsLayer.name = "Margins and Columns";
                }
                marginsLayer.locked = false; marginsLayer.visible = true;
                removePathsForArtboard(marginsLayer, idx);
                addMarginsAndColumnsToLayer(marginsLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, cols, thisVertGutter_pt, rows, thisHorGutter_pt);
            }

            var updateBaseline = applyAllChk.value || isBaselineChanged(current_pt, loaded_pt) || (baselineInc_pt > 0 && (!baselineLayer || !hasPathsForArtboard(baselineLayer, idx)));
            if (updateBaseline) {
                if (baselineLayer) baselineLayer.locked = false;
                if (baselineInc_pt > 0) {
                    if (!baselineLayer) {
                        baselineLayer = doc.layers.add();
                        baselineLayer.name = "Baseline";
                    }
                    baselineLayer.visible = true;
                    removePathsForArtboard(baselineLayer, idx);
                    addBaselineGridToLayer(baselineLayer, ab, idx, top_pt, bottom_pt, left_pt, right_pt, baselineStart_pt, baselineInc_pt);
                } else if (baselineLayer) {
                    removePathsForArtboard(baselineLayer, idx);
                    if (baselineLayer.pathItems.length === 0) {
                        baselineLayer.remove();
                        baselineLayer = null;
                    }
                }
            }
            
            var valuesToSave = {
                Top: addDefaultUnit(topInput.text, "margin"),
                Bottom: addDefaultUnit(bottomInput.text, "margin"),
                Left: addDefaultUnit(leftInput.text, "margin"),
                Right: addDefaultUnit(rightInput.text, "margin"),
                Columns: addDefaultUnit(colInput.text, "number"),
                Rows: addDefaultUnit(rowInput.text, "number"),
                VertGutter: addDefaultUnit(vertGutterInput.text, "gutter"),
                HorGutter: addDefaultUnit(horGutterInput.text, "gutter"),
                BaselineStart: addDefaultUnit(baselineStartInput.text, "margin"),
                BaselineInc: addDefaultUnit(baselineIncInput.text, "baseline")
            };
            
            if (vertGutterOverride[idx] !== undefined) { 
                valuesToSave.VertGutter = defaults.VertGutter.toString() + "mm"; 
            }
            if (horGutterOverride[idx] !== undefined) { 
                valuesToSave.HorGutter = defaults.HorGutter.toString() + "mm"; 
            }
            
            saveSettingsToXML(settingsXMLPath, idx, valuesToSave);
        }
        
        // Post-processing cleanup and locking
        if (marginsLayer && marginsLayer.pathItems.length === 0) {
            marginsLayer.remove();
        } else if (marginsLayer) {
            marginsLayer.locked = true;
        }
        if (baselineLayer) {
            baselineLayer.locked = true;
        }
        
        w.close();
    };

    function checkGridFit(abIdx, t_pt, b_pt, l_pt, r_pt, c, r, vg_pt, hg_pt) {
        var rect = doc.artboards[abIdx].artboardRect;
        var artW = rect[2] - rect[0] - l_pt - r_pt; var artH = rect[1] - rect[3] - t_pt - b_pt;
        var minW = mmToPt(1), minH = mmToPt(1);
        var failCol = false, failRow = false;
        if (c > 1) {
            var gutW = (c - 1) * vg_pt;
            if (artW <= gutW || (artW - gutW)/c < minW) { failCol = true; }
        }
        if (r > 1) {
            var gutH = (r - 1) * hg_pt;
            if (artH <= gutH || (artH - gutH)/r < minH) { failRow = true; }
        }
        return {failCol: failCol, failRow: failRow};
    }

    w.center(); 
    w.show();
}

showMarginsDialog();



 

TOPICS
Bug , How-to , Scripting , SDK
99
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Aug 23, 2025 Aug 23, 2025

@SmythWharf I probably ask an AI for that technically! 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 23, 2025 Aug 23, 2025
LATEST

I don't think AI is there yet, at least not for the hard Illustrator Scripting questions.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines