JavaScript Hook for 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

1 Like

I suspect you want to follow an existing example.

The place to look, I suspect, is https://github.com/discourse/discourse/blob/f62b8990acb9ce4af8bfc67fc80dc0847177e458/app/assets/javascripts/discourse/components/d-editor.js.es6

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.

1 Like

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.

3 Likes

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

1 Like