JavaScript Hook for Composer

AI-generated summary

The discussion revolves around creating a JavaScript hook for the Composer to enable a popup search feature. AlexanderFillbrunn requests guidance on accessing the composer element and having the plugin notified when the user types a specific sequence of characters. merefield suggests looking into the d-editor.js.es6 file and specifically the didInsertElement method, as well as the _applyCategoryHashtagAutocomplete method for inspiration.

To initialize this functionality, AlexanderFillbrunn inquires about the best place to start, and merefield recommends overriding the didInsertElement method in the plugin’s initializer. This can be achieved by using the api.modifyClass method, as demonstrated in the discourse-topic-previews plugin.

AlexanderFillbrunn expresses gratitude and confidence that this solution will work, enabling the creation of a custom popup search feature for the Composer.

Hi,
I had a previous post that did not get any response, maybe because the request was too narrow. So here I try again: I would like to hook into the compose editor so that when the user types a certain sequence of characters (e.g. --) followed by a query, I can show a popup with search results. Once the user clicks one of those, a normal link is inserted where the query was typed. What is best practise to access the composer element and have my plugin notified once the user composes a post? I had a look at the plugin API and some plugins on GitHub, but could not find any good example.
Kind regards
Alexander

I suspect you want to follow an existing example.

The place to look, I suspect, is discourse/app/assets/javascripts/discourse/components/d-editor.js.es6 at f62b8990acb9ce4af8bfc67fc80dc0847177e458 · discourse/discourse · GitHub

Specifically:

  didInsertElement() {
    this._super(...arguments);

    const $editorInput = $(this.element.querySelector(".d-editor-input"));
    this._applyEmojiAutocomplete($editorInput);
    this._applyCategoryHashtagAutocomplete($editorInput);

And maybe take a look at:

  _applyCategoryHashtagAutocomplete() {
    const siteSettings = this.siteSettings;

    $(this.element.querySelector(".d-editor-input")).autocomplete({
      template: findRawTemplate("category-tag-autocomplete"),
      key: "#",
      afterComplete: () => this._focusTextArea(),
      transformComplete: obj => {
        return obj.text;
      },
      dataSource: term => {
        if (term.match(/\s/)) {
          return null;
        }
        return searchCategoryTag(term, siteSettings);
      },
      triggerRule: (textarea, opts) => {
        return categoryHashtagTriggerRule(textarea, opts);
      }
    });
  },

NB I’ve not exploited this myself, but that’s my guess.

Hi @merefield,
thanks a lot, this is already quite helpful. Just where is the best place to initialize this? Should I check in my plugin’s initializer function whether .d-editor-input element exists and hook it up accordingly, or is there a place to register the plugin as an extension to the compose view, so that it only gets loaded when the user actually opens the composer.
Kind regards
Alexander

This is a Component, handilly, so you would want to override this method didInsertElement() in your initializer.

Example:

withPluginApi('0.8.12', (api) => {

      api.modifyClass('component:load-more'

from here https://github.com/paviliondev/discourse-topic-previews/blob/master/assets/javascripts/discourse/initializers/preview-edits.js.es6

If you are lucky you can just call this._super(); and append your additional logic at the end.

Perfect! Thanks a lot. I think this will do the trick.