まさかの2日連続投稿ですが、ただの続きです。
昨日のスクリプトですが、せっかく正規表現を使っているのになぜか一文字ずつ検索していました。あほか。
一応動くとはいえ文字が多くなると激重だったので、勉強もかねて書き直したものが下です。パフォーマンスの改善に加えて、せっかくなので相対値だけじゃなくて絶対値指定? もできるようにしました。
// 正規表現にマッチする文字が並んでるときだけ指定量トラッキング// 下の例だと、「正規表現にマッチする」を処理した場合は// 「マ」「ッ」に-20のトラッキングがかかります。// 09.08.06修正// ・一文字ずつ現在値から増減するか、全文字を指定した値に変更するか、選べるようにしました// ・動作が劇的に速くなりました (function(){// ----------------------------var amount = -20 var charClass = "[ァ-ン]"; // エスケープとかは自分でやってねvar relative = true; // true: それぞれ現在値から増減 false:すべて指定した値に変更// ----------------------------// 以下本体 =================================================if ( selection.length == 0 ) {alert("何か選択して!"); return; }var sel = selection; charClass += "+"; // 量指定子追加var rex = newRegExp(charClass,"g"); for ( var i = 0, len = sel.length; i < len; i++ ) {var tmp = sel[i]; if ( tmp.typename != "TextArtItem" ) {alert("テキストじゃないので飛ばします"); continue; } tmp = tmp.textRange(); // textRangeオブジェクトに変更var contents = tmp.contents; var m = []; while ( m = rex.exec(contents) ) {var index = m.index; if ( index == contents.length - 1 ) {break; }// 最後の文字ならループ抜けるvar range = tmp.textRange(index, rex.lastIndex -2); // 見つかった文字列の、最後から2番目の文字まで// 相対指定かどうかで処理を分ける。// relativeがtrueのときは現在の値を増減するので一文字ずつ処理するif ( relative ) {var chars = range.characters; for ( var j = 0, c_len = chars.length; j < c_len; j++ ) { chars[j].tracking += amount; }}else{ range.tracking = amount; // 絶対量ならいっぺんにいける}}// whileループここまで rex.lastIndex = 0; // 検索開始位置リセット}// 選択オブジェクトループここまでalert("おしまい!"); })();
要するに、量指定子を使ってトラッキングをかける範囲をダイレクトに取得するようにしたってことです。おかげで次の文字がどうとか判定する必要もなくなり、RegExpオブジェクトを一つにしぼれました。うーん、昨日の自分が何を考えていたのかわからない。
相対値でなく全部同じ値にする場合はtextRangeオブジェクトのtrackingプロパティを使えば一文字ずつ処理する必要がなくなるので、より速くなります(よほど大量にヒットしなければ大差ないですが)。
ただ、一つの状況に最適化すると応用が利かなくなるというわけで、characterオブジェクトにあってtextRangeオブジェクトにないプロパティを操作したい場合にはいろいろ書き換えが必要になってしまいますね。たいしたことないけど。