質問: txt1 + "actionscript(値)" + txt2; } みたいな感じです。 これを実現するactionscript,または方法はあるのでしょうか。 そんなことも知らないのか! などと思われそうな気もしますが,ここでの質問は初心者ですのでよろしくおねがいします。
回答: フォーカスに関する制御を担当する、selection というクラス( mx 以前ではオブジェクト)があります。 テキストフィールド内にある入力カーソル(点滅している” | ”型のカーソル)の位置は selection.getcaretindex メソッドで、表示されている文字列は textfield クラスの text プロパティで取得できます。 text プロパティには文字列が入っているので、文字列でできることは一通り可能です。 取得したカーソルの位置を境に2つに分割し、任意の文字列を挿入してはいかがでしょう。 仮に、ステージに「テキスト入力」にしたテキストフィールドがあるとします。 入力カーソルの位置が変わる可能性があるのは 1) キー入力が行われた時 2) マウスでテキストフィールド内をクリックされた時 ですから、これらのイベントを使って監視します。 1) は key クラスの onkeyup 、2) はムービークリップの onmouseup か mouse クラスの onmouseup イベントが利用できます。 どちらの場合も処理は同じなので、関数を1つ作り、これをイベント発生時に呼ぶ関数として登録しておくと便利です。 取得したカーソルの位置は、変数に保存しておきます。 この位置を元にテキストフィールドの内容を分割し、指定の文字列を挿入する関数を作ります。 後は、テキストを挿入する時に、挿入する文字列を引数にしてこの関数を呼ぶだけです。 スクリプトにすると、大体、次のようになります。 このスクリプトは、メインのタイムラインに設定してください。 ステージに、「テキスト入力」にしたテキストフィールド” editor ”があるものとします。 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください) //入力カーソル位置を保持 edit_pos = 0; ///////////////////////////////////////// //入力位置を把握する関数 ///////////////////////////////////////// function get_insertposition() { //編集画面にフォーカスがある場合のみ、文字カーソルの位置を取得 if( selection.getfocus() == "_level0.editor" ) { edit_pos = selection.getcaretindex(); } } ///////////////////////////////////////// //指定の文字列を、現在の入力位置に挿入 //引数:挿入する文字列 ///////////////////////////////////////// function insert_text( insert_str ) { var head , tail , org_length , insert_length; //編集前の文字列と挿入する文字列の長さを取得 org_length = editor.text.length; insert_length = insert_str.length; //編集画面のテキストを、現在の入力位置で分割 head = editor.text.substring( 0 , edit_pos ); tail = editor.text.substring( edit_pos , org_length ); //指定の文字を挿入 editor.text = head + insert_str + tail; //選択範囲を利用して入力カーソルを移動 edit_pos += insert_length; selection.setfocus( "editor" ); selection.setselection( edit_pos , edit_pos ); } //キー入力があった時とマウスのボタンが押された時、 //入力カーソルの位置を監視 key_obj = new object(); key.addlistener( key_obj ); key_obj.onkeyup = get_insertposition; mouse_obj = new object(); mouse.addlistener( mouse_obj ); mouse_obj.onmouseup = get_insertposition; get_insertposition 関数では、入力カーソルの位置を getcaretindex で取得し、この位置を変数 edit_pos に保存しています。 この関数は、キーを押して離した時と、マウスのボタンを押して離した時に呼び出されます。 key クラスや mouse クラスは、key.onkeyup = ・・・というように、クラス(のオブジェクト)に直接イベント発生時の処理を定義することができません。 これらのクラスでイベントを利用する時は、イベントの通知を代理で受け取る”リスナーオブジェクト”が必要です。 リスナーオブジェクトは汎用型である object 型の変数を作り、これを addlistener メソッドで登録します。 これらのイベントが発生するのは、テキストフィールド内でキーボードやマウスを操作した時とは限りません。例えばマウスのボタンは、スクリプトを挿入するボタンをクリックする時にも押されるので、onmouseup イベントはこの時にも発生します。 ムービー内のボタンをクリックすると、フォーカスが外れて文字入力カーソルは消えますから、getcaretindex の戻り値は -1 になります。 この状態で文字を挿入しようとすると、テキストフィールドに格納された文字列の分割に失敗し、テキストフィールドの先頭にしか挿入されなくなってしまいます。 そこで、イベント発生時に条件を付け、テキストフィールドが対象の時にキーまたはマウスを操作した場合、つまり、テキストフィールド” editor ”にフォーカスが当たっている時だけ、入力カーソルの位置を保存することにします。 フォーカスが当たっているインスタンスは、selection クラスの getfocus で取得できます。 trace アクションで見てみると分かりますが、getfocus の戻り値はレベルからの絶対パスです。通常はステージは _level0 ですから、ステージにあるテキストフィールド editor にフォーカスがある時は、” _level0.editor ”という文字列が返されます。 insert_text は実際にテキストを挿入する関数です。 例えば” _root.stop(); ”というスクリプトを挿入するボタンでは、これを引数として on(release) { insert_text( "_root.stop();\n" ); } というように呼び出してください。 最後の” \n ”は改行のコードで、入れておくと改行も挿入されます。 文字列を引数とするスクリプトは、 insert_text( "_root.gotoandplay( \"start\" );\n" ); このように ¥ でつなぐと、" " の部分で切られずに関数に文字列が渡ります。 insert_text 関数の中でやっていることは、ご質問文にある > txt1 = txt の1文字目からカーソルまで; > txt2 = txt のカーソルから最終文字まで; > txt = txt1 + "actionscript(値)" + txt2; と、全く同じことです。 入力カーソルの位置を境にしてテキストフィールドに入っている文字列を分割し、作業用変数 head に前半部分、tail に後半部分を入れて、引数で渡されてきた文字列を連結しています。 テキストエディタでは普通は、文字を挿入した分だけカーソルもずれて連続的に入力できるものですが、flash のテキスト入力では、スクリプトで操作して文字を挿入した場合はカーソルが移動しません。 例えば、テキストフィールドの表示が //サンプル trace( "サンプル" ); | (↑” | ”は入力カーソルです) だとして、ここに” _root.stop(); ”をスクリプトで挿入すると、 //サンプル trace( "サンプル" ); |_root.stop(); となり、入力位置は変わらないままです。 ざっと見た限りでは、selection.getcaretindex でカーソルの位置の取得はできても、任意の位置にカーソルを移動するメソッドはないようです。 selection クラスには、指定の範囲を選択状態にする setselection というメソッドがあります。 字数は配列と同様に0から数えますので、例えば selection.setselection( 0 , 4 ); とすると、フォーカスの当たっているテキストフィールドの最初から5文字までが選択された状態になります。 この時、入力位置を表すカーソルは5文字目(インデックス値では4)の位置に移動しています。 insert_text 関数内ではこの特徴を利用して、擬似的にカーソルを進めています。 setselection は、フォーカスの当たっているテキストフィールドでなければ何も起こりません。 insert_text 関数が呼び出されるのは、スクリプトを挿入するボタンをクリックした時などです。 ボタンをクリックした時点で editor はフォーカスを失っていますから、setfocus で再度 editor にフォーカスを与えています。 --------------------------------------------------------- ご承知の上だとは思いますが。 flash は、本格的なアプリケーションを作ることが目的のソフトではありません。 actionscript でも、指定された位置に文字を挿入するくらいのことであれば、まあ、一応はできるという程度です。 エディタの機能を付け足していこうとすると、どうしても、弱い部分が目立ってきます。 例えば、テキストフィールドの都合上、文字を挿入する位置によっては挿入した文字が上に送られて見えなくなってしまうことがあり、これはエディタとしては使いにくいです。 テキストフィールドや変数内に作ったスクリプトはただの文字列で、スクリプトとして機能はしません。sharedobject に書き出して保存することはできても、sharedobject の内容を他のムービーに読み込んでも文字列として扱われるだけです。 テキストファイルに書き出せるなら、外部ファイルとして #include で組み込む手もありますが、flash 単体ではファイル出力は無理です。 編集したものを有効な形式で保存できないのは、エディタとしては致命的な欠陥です。 テキストフィールドの内容をコピーして他の fla ファイルに貼り付けるくらいなら、最初から「アクション」パネルで編集した方が早くて確実です。 エディタはスクリプトの勉強としては面白い題材ですが、実用レベルのものを作るとなると、flash ではかえって難関が多く、難しいのではないでしょうか。