Skip to main content
Participating Frequently
May 11, 2023
Answered

Startup Scriptでの配置のevent Listenerの処理エラーについて

  • May 11, 2023
  • 9 replies
  • 6658 views

IndesignファイルにaiまたはPDFをDrag & Dropしたときに、[オブジェクトレイヤーオプション]の[リンクの更新オプション]を『Indesignでのレイヤー表示を有効』から『PDFレイヤーの表示を有効』に変更するStartup Scriptを作りたいと思っています。

 

現在作成したScriptは以下です。

#targetengine "ddListener"

var main = function() {

var
onAfterPlaceListener = app.eventListeners.itemByName ( "onAfterPlace" ),

onAfterPlaceHandler = function(evt){
evt.parent.pdfs[0].graphicLayerOptions.updateLinkOption = UpdateLinkOptions.APPLICATION_SETTINGS;
};

if ( !onAfterPlaceListener.isValid ) {
onAfterImportListener = app.eventListeners.add("afterPlace", onAfterPlaceHandler );
onAfterImportListener.name = "onAfterPlace";
}

}

main();

 

これを[Startup Scripts]フォルダに入れて動作させると、Drag & Dropをしたときにエラーが表示されますが、「このイベントハンドラーを無効にしますか?」で[いいえ]を選択するとリンクの更新オプションは書き換えられています。

また複数ファイルをまとめてDrag & Dropしたときも複数回エラーが表示されますが、すべて「いいえ」を選択すると書き換えられています。

 

根本的に何かを間違っているのかもしれないのですが、修正方法をご教示いただければ幸いです。
宜しくお願い致します。

Correct answer kawamoto_α

「beforeUpdateからafterUpdateの間無効にする」作戦で、リンク更新時に発動するのを回避してみました。

#targetengine "ddListener"
var ddTarget=null;
var ddFlag=true;
addEL(app,"afterPlace",ddHandler1,"ddHandler1");
addEL(app,"afterLinksChanged",ddHandler2,"ddHandler2");
addEL(app,"beforeUpdate",ddHandler3,"ddHandler3");
addEL(app,"afterUpdate",ddHandler4,"ddHandler4");

function addEL(obj,type,handler,name){
    if (obj.eventListeners.item(name).isValid) obj.eventListeners.item(name).remove();
    obj.addEventListener(type,handler).name=name;
}
function ddHandler1(ev) {
    if(!ddFlag)return;
    if(ev.target.constructor.name=="Rectangle" && ev.target.pdfs.length>0){
        ev.target.pdfs[0].graphicLayerOptions.updateLinkOption=UpdateLinkOptions.APPLICATION_SETTINGS;
    } else if (ev.target.constructor.name=="PDF" && ev.target.graphicLayerOptions.updateLinkOption!=UpdateLinkOptions.APPLICATION_SETTINGS) {
        ddTarget=ev.target;
    }
}
function ddHandler2(ev) {
    if (ddTarget != null) {
        ddTarget.graphicLayerOptions.updateLinkOption=UpdateLinkOptions.APPLICATION_SETTINGS;
        ddTarget=null;
    }
}
function ddHandler3(ev) {
    ddFlag=false;
}
function ddHandler4(ev) {
    ddFlag=true;
}

9 replies

Participant
February 9, 2025

 

 

 

 
 
 

 

 
  •  
  • Regarding event listener processing error in Startup Script
 
Regarding event listener processing error in Startup Script

 

 
May 10, 2023

Copy link to clipboard

 
 

I would like to create a Startup Script that changes the "Link Update Options" in "Object Layer Options" from "Enable layer display in Indesign" to "Enable PDF layer display" when an ai or PDF is dragged and dropped into an Indesign file.

 

The script I have created so far is as follows:

#targetengine "ddListener"

var main = function() {

var
onAfterPlaceListener = app.eventListeners.itemByName ( "onAfterPlace" ),

onAfterPlaceHandler = function(evt){
evt.parent.pdfs[0].graphicLayerOptions.updateLinkOption = UpdateLinkOptions.APPLICATION_SETTINGS;
};

if ( !onAfterPlaceListener.isValid ) {
onAfterImportListener = app.eventListeners.add("afterPlace", onAfterPlaceHandler );
onAfterImportListener.name = "onAfterPlace";
}

}

main();

 

If you put this in the Startup Scripts folder and run it, an error will be displayed when you perform a drag and drop, but if you select No when asked "Do you want to disable this event handler?" the link update option will be rewritten.

Also, if you drag and drop multiple files at the same time, multiple errors will be displayed, but they will all be overwritten if you select "No."

 

I may be doing something fundamentally wrong, but I would be grateful if you could tell me how to fix it.
Thank you in advance.

Participating Frequently
May 15, 2023

monokanoさまにご回答いただいたコードを基に、直前にafterImportイベントが発生した場合のみに動作させることとして作成してみました。

#targetengine "ddListener"

if (app.eventListeners.itemByName('updateOption')!=null) {
  app.eventListeners.itemByName('updateOption').remove();
}

var arEv = [];

var listner2 = app.addEventListener (
  'afterPlace', 
  function (ev) {
  	var tg = ev.target;
        if (tg.constructor.name === "Rectangle") {
            try {
                if(arEv.length > 0 && arEv[arEv.length-1].constructor.name == 'Document'){
                    arEv.pop();
                    tg.graphics[0].graphicLayerOptions.updateLinkOption = UpdateLinkOptions.applicationSettings;
                }
            } catch (e) {};
        }
  }
);

var listner = app.addEventListener (
  'afterImport',
  function (ev) {
        arEv.push(ev.target);
  }
);
listner.name = 'updateOption';

 

ひとまず私の現時点での検証では問題ないと思っておりますが、id.omegaさまが返信されている『設定を変更した時に内部的に画像の再配置などが行われて発生するイベント』がわかっていないため、この「再配置」でafterImportが発生するのであれば失敗するのかもしれません。

これではうまくいかないケースが考えられるようでしたら、ご指摘いただけると幸いです。

kawamoto_α
Participating Frequently
May 15, 2023

ファイルをインポートした後、ドキュメントに配置する前(マウスカーソルに抱えている状態)でESCキーを押してキャンセルすると、arEvの中身が残り続けてしまいそうな気がします。

Participating Frequently
May 15, 2023

kawamoto_αさま

早速にご返信いただきましてありがとうございます。助かります。

 

『ファイルをインポートした後、ドキュメントに配置する前(マウスカーソルに抱えている状態)でESCキーを押してキャンセル』をして、再度配置した直後のafterImportイベント発生時のarEv.lengthは「0」でした。

 

これは 7行目のvar arEv = []; が常に処理されるということになるのか、一連の処理以降にarEvが破棄されているのかはもう少し調べてみようと思います。

kawamoto_α
Participating Frequently
May 13, 2023

これはとにかくいつでも「PDFレイヤーの表示を有効」になってほしいという、ものかのさん的な人向け。
afterPlaceイベントの中で変更できないのなら、afterPlaceではPDFオブジェクトを取得するだけにしといて、afterPlaceの後に必ず発生しているっぽいafterLinksChangedイベント(targetはドキュメント)内で設定しようという作戦です。

 

わざわざ配置オプションを表示して「InDesignでのレイヤー表示を有効」で配置しても「PDFレイヤーの表示を有効」になりますのでご注意ください。

#targetengine "ddListener"
var ddTarget=null;
addEL(app,"afterPlace",ddHandler1,"ddHandler1");
addEL(app,"afterLinksChanged",ddHandler2,"ddHandler2");

function addEL(obj,type,handler,name){
    if (obj.eventListeners.item(name).isValid) obj.eventListeners.item(name).remove();
    obj.addEventListener(type,handler).name=name;
}
function ddHandler1(ev) {
    if(ev.target.constructor.name=="Rectangle" && ev.target.pdfs.length>0){
        ev.target.pdfs[0].graphicLayerOptions.updateLinkOption=UpdateLinkOptions.APPLICATION_SETTINGS;
    } else if (ev.target.constructor.name=="PDF" && ev.target.graphicLayerOptions.updateLinkOption!=UpdateLinkOptions.APPLICATION_SETTINGS) {
        ddTarget=ev.target;
    }
}
function ddHandler2(ev) {
    if (ddTarget != null) {
        ddTarget.graphicLayerOptions.updateLinkOption=UpdateLinkOptions.APPLICATION_SETTINGS;
        ddTarget=null;
    }
}

 

monokano
Community Expert
Community Expert
May 13, 2023

すごいですね!

このスクリプトは既存のリンクにもリンク更新時に発動するので、他所の他人が作ったinddを開くことがある環境で何も考えずにstartup scriptsに入れるのは、私でもおすすめしないのですけど、理想の極北といった徹底ぶりがとてもおもしろいです。

inddを一から自分で作って最後まで自分だけで完結する場合には最高だと思います。

Participating Frequently
May 14, 2023

このような書き方ができるんですね。
変数を用意してターゲットがPDFの時に処理するか処理しないかを分岐できないかと試行錯誤してみてたのですが、書き方が悪いのか結果的にうまくいきませんでした。設定を変更した時に内部的に画像の再配置などが行われて発生するイベントを把握するのは容易ではないですね。

もう一つ別の可能性として、beforeSaveなど、保存や印刷・書き出し前などにドキュメント内のPDFをチェックして変更する方法もあるのかなと思います。入口ではなくて出口を塞いで捉える作戦です。出口側なら変更するかしないか確認しながら処理することもできるのではないかと思います。

kawamoto_α
Participating Frequently
May 12, 2023

当初の問題は、「afterPlaceイベントがRectangleとPDFの2つで発生しているのに、スクリプトはRectangleしか想定してなかった」ことが原因で、それはものかのさんがやっているように「targetのconstructor.nameを見て(あるいはTen Aさんのように文字列で比較して)Rectangleのときのみ処理する」ことで解決してるわけですよね。

 

で、新たな問題として
・ドラッグ&ドロップの仕方によってはafterPlaceイベントがPDFだけでしか発生しない
・targetがPDFのとき、そのPDFのupdateLinkOptionを変更できない
が出てきたと。

 

確認ですが、スクリプトでドラッグ&ドロップによる配置とそれ以外の方法による配置を区別するのは困難です。また、afterPlaceイベントは再リンクやリンク更新などでも発生します。そのへんは覚悟の上でしょうか?(つまりあらゆる場合に『PDFレイヤーの表示を有効』になってほしいと考えてるのでしょうか)

monokano
Community Expert
Community Expert
May 12, 2023

私は「あらゆる場合に『PDFレイヤーの表示を有効』になってほしい」ですね。

 

A.配置したら常に配置ファイルのレイヤー表示が反映されるようにしたい

B.indd上で配置ファイルのレイヤー表示をON/OFFしたい

 

どちらが需要が多いかといえば、圧倒的大大大多数でAでしょう。

Bは、そもそもオプション機能として使いたい時に使うようなもののはずです。それがデフォルトで強制されている現状がむしろ変だと考えています。

Ten A
Community Expert
Community Expert
May 11, 2023

諸々勘案すると、こうですかねぇ…

 

 

#targetengine session
if (app.eventListeners.itemByName('updateOption')!=null) app.eventListeners.itemByName('updateOption').remove();
var listner = app.addEventListener ('afterPlace', function (ev) {
  if (ev.target=="[object Rectangle]") ev.target.graphicLayerOptions.updateLinkOption = 1819243873;
);
listner.name = 'updateOption';

 

ちょっと直しました(^-^;

 

Participating Frequently
May 12, 2023

Ten Aさま

 

ご回答ありがとうございます。

最終行1行前を )}; に修正して実行しましたが、再度同様のエラーが発生しました。

なお、正解とさせていただいたmonokanoさまの返信にコメントしていますが、都合上、afterPlaceイベントでは想定した処理ができないことがわかりました。

monokano
Community Expert
Community Expert
May 11, 2023

 

 

#targetengine session

if (app.eventListeners.itemByName('updateOption')!=null) {
  app.eventListeners.itemByName('updateOption').remove();
}

var listner = app.addEventListener (
  'afterPlace',
  function (ev) {
  	
  	var tg = ev.target;
  	
	if (tg.constructor.name === "PDF") {
		try {
			tg.graphicLayerOptions.updateLinkOption = UpdateLinkOptions.applicationSettings;
			alert("できた:PDF");
		} catch (e) {alert("できない:PDF");};
		
	} else if (tg.constructor.name === "Rectangle") {
		try {
			tg.graphics[0].graphicLayerOptions.updateLinkOption = UpdateLinkOptions.applicationSettings;
			alert("できた:Rectangle");
		} catch (e) {alert("できない:Rectangle");};
	}
  }
);
listner.name = 'updateOption';

 

 

 

調べてみたら、かなり複雑でした…。がんばって説明してみます。

 

afterPlaceでは、aiファイルを配置すると、ev.targetが「PDF」「Rectangle」の2種類が返ってきます。

 

そのうち、updateLinkOptionを設定できるのは「Rectangle」の方だけです。上記スクリプトでそれがよくわかります。

 

なお、PDFからparentを取得すると、それも「Rectangle」なのですが、試してみるとこちらはupdateLinkOptionを設定できません。設定できるのは、afterPlaceで直接targetとして返される「Rectangle」だけです。

 

そして、「Rectangle」が返されるのは、ページ上に直接ドロップしたり、ページ上に直接配置した場合だけです。

 

画像フレームなどの既存のオブジェクト内に配置されると、targetは「PDF」のみで、「Rectangle」は返ってきません。この場合は、afterPlaceでの変更は無理のようです。

Participating Frequently
May 11, 2023

手元で試していたのですが、どうやらafterPlaceイベントが2回呼び出されているようです。

1回目はaiファイルが配置された後で、この時のev.targetはRectangle。

2回目はev.target.pdfs[0].graphicLayerOptions.updateLinkOptionを変更した後、再度afterPlaceイベントがPDFをターゲットに起こるようです。

Object does not support the property or method 'pdfs' エラーは2回目のafterPlaceイベントが起こった時にpdfsプロパティに対応していないために起きていると考えられます。

 

私が検証できたのはここまでなのですが、ev.targetがPDFの時にupdateLinkOptionを変えようとすると無限ループになってしまうのか?あるいは何か良い回避方法があるのかが気になります。

monokano
Community Expert
Community Expert
May 11, 2023

試したら混乱しまくりましたが(笑)、確かにその通りでした。

> 無限ループになってしまうのか?

これは悩ましいですねえ…。

Participating Frequently
May 11, 2023

使用環境とエラーメッセージを記入しておらず失礼いたしました。

追記いたします。

 

▼使用環境

InDesign 2022 (Windows)

InDesign 2023 (Windows)

 

▼エラーメッセージ

 

Ten A
Community Expert
Community Expert
May 11, 2023

色々な書き方が出来るのですが、ストレートに書くとこんな感じかな…

 

#targetengine session

if (app.eventListeners.itemByName('updateOption')!=null) {
  app.eventListeners.itemByName('updateOption').remove();
}

var listner = app.addEventListener (
  'afterPlace',
  function (ev) {
    ev.parent.pdfs[0].graphicLayerOptions.updateLinkOption = 1819243873;
  }
);

listner.name = 'updateOption';
Participating Frequently
May 11, 2023

ご回答ありがとうございます。

 

いただいたscriptを試しましたが、同様にエラーが発生しました。

 

お手数ですが、ご確認いただけますと幸いです。

宜しくお願い致します。

Participating Frequently
May 11, 2023

if文のなかに

onAfterImportListener

がありました。こちらを

onAfterPlaceListener 

に修正しても同様でした(複数イベントをトリガーに開発していて、投稿後に記述が間違っていることに気が付きました)。