InDesignのExtendScriptでは、テキストに関するサブクラスがたくさんあります。これらを使って「選択しているオブジェクトはなにか?」というのをよく実装するわけですが、毎度毎度「TextStyleRangeと、あとなんだっけ……」みたいに全部をパッと思い出せないんですよね。
なのでちょっとまとめてみました。InDesignスクリプターの方にお役立ていただけると嬉しいです。
- Story
- Character
- Word
- Line
- TextColumn
- Paragraph
- TextStyleRange
- InsertionPoint
それぞれ個別に説明はしませんが、Textオブジェクトのサブクラスだけでこれだけあります*1。ほかにもTextFrame、Cell、Tableなども含めるかどうか。
で、これだけあるので、「選択しているオブジェクトがテキストの時」という条件をトリガーにする場合、どのように実装するのがベターか悩むんですよね。
var sel = app.activeDocument.selection[0]; if (sel.constructor.name === "Character" || sel.constructor.name === "Word" || sel.constructor.name === "Line" || sel.constructor.name === "TextColumn" || sel.constructor.name === "Paragraph" || sel.constructor.name === "TextStyleRange" || sel.constructor.name === "InsertionPoint") { //なんらかの処理 }
って総当たりでやるのがセオリーなんですが、冗長ですよね。
ほかには、例えば選択したオブジェクトがtexts
プロパティを持っているかどうか、というやり方もあります。
var sel = app.activeDocument.selection[0]; if (sel.hasOwnProperty("texts")) { //なんらかの処理 }
ただ、これには前掲のリストに加えて、TextFrameオブジェクトやCellオブジェクトも問答無用で含まれます。どちらのやり方も一長一短ですので、目的とする条件を達成するのにもっとも効率がいい書き方を選べればいいと思います。
ECMAScript5で配列オブジェクトに実装されたsome
メソッド*2をポリフィルしておいて、こんな書き方をすることもたまにあります。
var acceptClasses = [ "Text", "TextColumn", "Story", "Paragraph", "Line", "Word", "Character", "TextStyleRange", "Table", "Cell" ]; if (app.selection.length !== 1 || !acceptClasses.some(function(el){ return el === app.selection[0].constructor.name; })) { myerror("文字か表組を選択してから実行してください"); }
ちなみに僕が使っているsome
メソッドのコードはこちら(Gistです)。
まぁ、ここまで書いたらアロー関数も使いたいよね…w
*1:Storyは正確にはTextオブジェクトのサブクラスではないです
*2:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some