タイトル事前入力時にエディタをフォーカス

URLがこれに似ています。

https://forum.example.com/new-message?groupname=moderators&title=Help+me+with+some+task+please

これをサイトにリンクして、ユーザーがフォーラムで質問できるようにしています。タイトルにはさまざまな値を設定して、ユーザーが疑問に思っているトピックに合わせてタイトルを事前入力できるようにしたいのですが、エディターにフォーカスを当てたいと思っています。

これを変更する方法を探していて、focusTarget の定義が含まれる composer.js ファイルを見つけました。タイトルが渡されれば、この動作をサポートするように簡単に変更できそうです。

問題は、focusTarget が実際にどこで呼び出されているのかわからないことです。長年プログラミングをしていますが、Ember は初めてで、JavaScript プログラミングの経験はほとんどありません。

この問題へのアプローチに関するヒントがあれば、大歓迎です(適切なマニュアルへのポインタ付きの rtfm も歓迎です)。

Cheers

お探しのものはこれだと思います。

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/composer-editor.js#L159-L164

focusTarget の値が変わるたびに、この setFocus 関数が呼び出されます。

はい、そのコードで動作します。しかし、このメソッドでタイトルを取得し、エディタにフォーカスを設定するためにどのコードを変更する必要があるのかはわかりません…

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/services/composer.js#L218-L243

このようなことができると思います。これでうまくいくはずです。

import putCursorAtEnd from "discourse/lib/put-cursor-at-end";

api.onAppEvent("composer:open", ({ model }) => {
  if (model.title !== "") {
    scheduleOnce("afterRender", () => {
      putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
    });
  }
});
「いいね!」 1

ほぼ動作するところまで来ました。コードを実行すると、scheduleOnce が定義されていないというエラーが発生します。api.scheduleOnce を試しましたが、scheduleOnce は Ember のもののようです。コンポーネントにこのインポートを追加しようとしましたが、トップレベルでのみインポートが許可されるというエラーが発生しました。
import { scheduleOnce } from "@ember/runloop";

何か些細なことを見落としているのだと思いますが、もう少し自分でいじってみます。しかし、あなたには明白なことかと思い、質問させていただきました。

いつもありがとうございます :slight_smile:

はい、インポートは正しいです。両方のインポートをファイルの先頭に配置すれば、問題なく動作するはずです。

「いいね!」 1

どこにファイルを置けばいいですか?ヘッド内でコンポーネントとして使用しようとしていました。以下は行ったことですが、ログに「scheduling afterRender」と表示され、その後scheduleOnceが存在しないというエラーが発生します。importをいくつか試しましたが、うまくいきません。JavaScriptのモジュールに関する経験不足が問題を引き起こしていると思われます。コンポーネント経由ではできない可能性があり、より完全なプラグインを作成する必要があるかもしれません。それを見てみます。再度、ご協力ありがとうございます :slight_smile:

<script type="text/discourse-plugin" version="1.8.0">
    api.onAppEvent("composer:open", ({ model }) => {
      console.log("composer open happened, model is: ", model);
      if (model.title !== "") {
        console.log("scheduling afterRender");
        scheduleOnce("afterRender", () => {
          console.log("after render happening");
          api.putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
        });
      }
    });
</script>

なるほど。そのファイルでJSを使用していると仮定していました。

管理UIから、次のように記述します。

<script type="text/discourse-plugin" version="1.8.0">
    const putCursorAtEnd = require("discourse/lib/put-cursor-at-end").default;
    const { scheduleOnce } = require("@ember/runloop");

    api.onAppEvent("composer:open", ({ model }) => {
      if (model.title !== "") {
        scheduleOnce("afterRender", () => {
          putCursorAtEnd(document.querySelector("textarea.d-editor-input"));
        });
      }
    });
</script>

ちなみに、Theme CLIの使用を強くお勧めします。テンプレートからテーマコンポーネントを作成し、Discourseと同期してライブリフレッシュを行い、エディタを使用して変更を更新できます。UIを使用するよりもはるかに簡単です!

「いいね!」 2

ありがとうございます。何か見落としていることに気づきました。テーマCLIを使用して編集するように設定します :slight_smile: :slight_smile:

「いいね!」 1

Arkshineさん、ありがとうございました。discourse_themeを使って最初のコンポーネントを作成できました :slight_smile:
このスレッドを見つけた方のために、実行したコマンドをいくつか紹介します。

gem install discourse_theme
npm install -g yarn
discourse_theme new <component-name>

その後、javascripts/discourse/api-initializers/<component-name>.js ファイルを編集し、GitHubにアップロードすれば、インストールしたり共有したりできます。
私のコンポーネントはこちらにあります。
ファイルを変更するたびに、サーバーのバージョンを自動的に更新する機能もあるようです。これは、より複雑なコンポーネントを作成する上で、良い機能だと思います。

Cheers

「いいね!」 1

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.