Skip to main content
dublove
Legend
May 16, 2026
Answered

Is it possible to capture the previous mouse action (the direction in which the object was moved)?

  • May 16, 2026
  • 3 replies
  • 52 views

Hi everyone~

It seems there’s a history feature, and I’d like to capture the direction in which I moved the object in the previous step.


For example:
I just dragged an object, and now I want to know the direction of the movement—whether it was left, right, up, or down.
If the object was moved both left and up at the same time, take the direction with the largest movement value.

Thank you.

    Correct answer rob day

    My main focus is on retrieving historical operations

     

    I don’t see any options in the API relating to history. You can get the bounds of a selection before and after it is moved via listeners—this displays the starting X position and the new position after a move (afterSelectionAttributeChange):

     

    #targetengine "session"

    var s = app.selection[0]
    //get the selection’s current X position
    alert("The selected object’s X position is:\r" + s.geometricBounds[1])
    app.eventListeners.add("afterSelectionAttributeChanged", getNewPosition);

    function getNewPosition(e){
    //get the new position after a move
    alert("You have moved the selection, it’s new x position is:\r" + s.geometricBounds[1])
    app.removeEventListener("afterSelectionAttributeChanged", getNewPosition);
    }

     

    Before and after alerts

     

     

    3 replies

    m1b
    Community Expert
    Community Expert
    May 17, 2026

    Hi ​@dublove, Rob has already given you a fantastic approach, which I think is better than mine, but for the sake of showing different ideas, here is my attempt (I hadn't seen Rob’s). My approach is simple: I use an invocation of the “Transform Again” menu.

    To test it, just select some items and arrow nudge them in the direction you want, then run script.

    This script may also help you with your other question about aligning objects to guides, but the main point was getting the direction of the last move.

    — Mark

    /**
    * @file Move To Margin.js
    *
    * Demonstration showing my technique for
    * getting the direction of the last translation.
    *
    * The script will move selected objects in the
    * direction of the last translation until they
    * hit the nearest margin.
    *
    * The idea is to first use a "nudge" arrow key
    * before running the script.
    *
    * @author m1b
    * @version 2026-05-17
    * @discussion https://community.adobe.com/questions-671/is-it-possible-to-capture-the-previous-mouse-action-the-direction-in-which-the-object-was-moved-1561822?tid=1561822
    */
    function main() {

    if (
    0 === app.documents.length
    || 0 === app.activeDocument.selection.length
    )
    return alert('Please select one or more page items and try again.');

    var doc = app.activeDocument;
    var items = doc.selection;
    var vector = getVectorOfLastTranslation(doc);

    if (!vector)
    return;

    for (var i = items.length - 1; i >= 0; i--)
    translateToMargin(items[i], vector);

    };
    app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Align To Margin');

    /**
    * Translates `item` so that it touched the nearest
    * page margin in the direction `vector`.
    * @author m1b
    * @version 2026-05-17
    * @param {PageItem} item - an Indesign page item.
    * @param {Array<Number>} vector - the direction of translation [vx, vy].
    */
    function translateToMargin(item, vector) {

    var page = item.parentPage;

    if (!page)
    // not on a page
    return;

    var pb = page.bounds;
    var mp = page.marginPreferences;

    var marginBox = {
    top: pb[0] + mp.top,
    left: pb[1] + mp.left,
    bottom: pb[2] - mp.bottom,
    right: pb[3] - mp.right,
    };

    // compute distance to bring leading edge flush with the nearest margin
    var t = distanceToBoxEdge(item.geometricBounds, marginBox, vector);

    if (null === t)
    // already past the margin in this direction
    return;

    // move it
    item.move(undefined, [vector[0] * t, vector[1] * t]);

    };

    /**
    * Returns a vector showing the direction of the last translation, if any.
    * @author m1b
    * @version 2026-05-17
    * @param {Document} doc - an Indesign document.
    * @returns {Array<Number>?} - [vx, vy]
    */
    function getVectorOfLastTranslation(doc) {

    var selection = doc.selection;

    // use Transform Again as a trick to get the translation
    var action = app.menuActions.itemByName('Transform Again');

    if (!action.enabled)
    // no previous transform
    return;

    var temp = app.activeDocument.rectangles.add();

    // detect direction of last translation
    var b = temp.geometricBounds;
    var p0 = [b[1], b[0]]; // [x, y]

    // perform the last transform
    doc.selection = [temp];
    action.invoke();

    // read the new position
    b = temp.geometricBounds;

    // cleanup
    temp.remove();
    doc.selection = selection;

    var p1 = [b[1], b[0]];
    var vx = p1[0] - p0[0];
    var vy = p1[1] - p0[1];

    if (0 === vx && 0 === vy)
    // no movement
    return;

    return [vx, vy];

    };

    /**
    * Returns number `t` such that translating the item by t * a vector
    * brings its leading edge flush with the closest edge of `marginBox`.
    * @author claude code
    * @version 2026-05-17
    * @param {Array} bounds - geometricBounds [top, left, bottom, right].
    * @param {Object} marginBox - { top, left, bottom, right }.
    * @param {Array<Number>} vector - the direction vector [vx, vy].
    * @returns {Number|null} - the scalar t, or null if no valid margin is found.
    */
    function distanceToBoxEdge(bounds, marginBox, vector) {

    var candidates = [];
    var vx = vector[0];
    var vy = vector[1];

    if (vx > 0)
    candidates.push((marginBox.right - bounds[3]) / vx);
    else if (vx < 0)
    candidates.push((marginBox.left - bounds[1]) / vx);

    if (vy > 0)
    candidates.push((marginBox.bottom - bounds[2]) / vy);
    else if (vy < 0)
    candidates.push((marginBox.top - bounds[0]) / vy);

    var minT = null;

    for (var i = 0; i < candidates.length; i++) {

    if (
    candidates[i] >= 0
    && (minT === null || candidates[i] < minT)
    )
    minT = candidates[i];

    }

    return minT;

    };

     

    rob day
    Community Expert
    Community Expert
    May 16, 2026

    The application can listen for events. There is AFTER_SELECTION_ATTRIBUTE_CHANGED and AFTER_SELECTION_CHANGED. Not sure what you are trying to do, but an AFTER_SELECTION_CHANGED should let you get the before and after positions

     

    https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Application.html

    dublove
    dubloveAuthor
    Legend
    May 16, 2026

    @rob day 

    As mentioned, aligning to guide lines may require four scripts (left, right, top, and bottom).

    This results in too many scripts and makes the process too complicated, so I want to use mouse gestures to combine these four scripts into one.

     

    It compares the last two historical operations to determine in which direction I moved the object.

    For example, if I move an object upward in the previous step and then run the script, and if the script can detect that the previous action was moving the object upward(For example, nesSb[0] > oldSb[0]), it should assume that I intend to align the top edge of the object to the nearest guide line.

     

     

    rob day
    Community Expert
    Community Expert
    May 16, 2026

    Here’s an afterSelectionChange event example:

     

     

    Community Expert
    May 16, 2026

    I don’t see a way , not from the History, the scripting DOM I can’t find any expose to mouse actions. You would need to know the position before moving, then compare it with the new position. Then comopare with geometric.bounds. If horizontal is larger then left/right, if vertical then up/down. 

     

    You’d have to somehow store the values before moving, possible maybe to write to the script label before moving, but you’d have to run a script before moving it so the label populates. 

     

    I’m not really sure of what you want to do here. Or why? 

    Typically if I need to move something the exact same distance I just use the Object>Transform Again options 

     

    Hard to know where to go with this.

     

    There are apps that can write the mouse events and track mouse movement. 

    I just don’t even know where to start. 

     

    Maybe tell us a bit more of what you’re trying to do?

    dublove
    dubloveAuthor
    Legend
    May 16, 2026

    Hi ​@Eugene Tyson 

    I want to combine the four scripts that align object to guide lines into a single script.
    Before running the script, I move the object slightly upward with the mouse.

    Next, I run the script, hoping it will read the “previous action” to automatically determine that I want to align it upward.
     

    Community Expert
    May 16, 2026

    Ok - absolutely no way would have guessed that.

    So InDesign scripting can’t read the previous mouse move or the last drag direction from History.

     

    Just an idea.

    Instead of detecting previous manual movement, the combined script might be able to determine the intended guide which would need to compare to the selected object position and nearby guides.

     

    Idea:

    Get geometricBounds
    Get page guides

    Measure distance - object edge/centre to nearby x y guides

    Pick nearest

    Closest guide is above (left/right/below) align up (left/right/down)

    This way you can nudge objects near a guide, then with a single script it should align to the closest guide automatically. 

     

    Put it in this kinda order might work:

    // codeIdea

    // Compare selected object's bounds to all guides

    // Find nearest guide

    // If nearest guide is horizontal 

    // align top/bottom/center Y to that guide

    // If nearest guide is vertical 

    // align left/right/center X to that guide

     

    Tracking the previous movement, I can’t find an access point for that in scripting, so this is the next best thing and might even be slightly more reliable. 

     

    As previous script here 

     

    Change the dialog with four buttons: Up, Down, Left, Right.

    But if you want the script to feel automatic, “align to nearest guide” is likely the better route.