Focus the editor when title is pre-filled

I’ve got a url similar to this:

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

That I link to on my site, to bring users to the forum to ask a question. I use various values for title to pre-fill the title with whatever topic they’re wondering about, and I would like the editor to be the focus.

I was looking to see how to modify this, and found the composer.js file with the focusTarget definition, which would be pretty easy to modify to support this behavior if the title were passed in.

The problem I’m finding is that I can’t see where focusTarget is actually called. I’ve been programming for many years, but new to Ember, and I’ve done relatively little javascript programming.

Any tips on how to approach this would be greatly appreciated (an rtfm with a pointer to a reasonable manual would be appreciated even)

Cheers

I think this is what you’re looking for:

Every time the focusTarget value changes, this setFocus function is called.

Right, that code is what makes it work. What I’m not sure about is what code I need to modify in order for this method to get the title, so I can appropriately set the focus to editor there…

I think you can do something like that. This should work.

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 Like

I’ve almost got this working – when the code is executing, I’m getting an error that scheduleOnce is not defined – I tried api.scheduleOnce, but it looks like scheduleOnce is an ember thing. I tried adding this import to my component, but got an imports only allowed at top level error.
import { scheduleOnce } from "@ember/runloop";

I’m guessing there’s something small I’m missing, and going to keep messing about with it, but thought I’d see if it was obvious to you.

Thanks again :slight_smile:

Yes, the import is correct. Put both imports at the top of the file and you should be good.

1 Like

What file should I put them in? What I was trying to do was just use it in – as a component – this is what I did, which results in the log “scheduling afterRender” showing up, then an error about scheduleOnce not existing. I have tried using the import a few ways, but it’s not working. I suspect my inexperience with modules in javascript is causing me issues. Maybe I can’t do it via a component, and need to do some more full plugin. Will take a look at that – thanks again for your help :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>

Oh, I see. I assumed you used JS in its files.

From the admin UI, then, you would write:

<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>

On a side note, I highly encourage you to use the Theme CLI. You can create a theme component from a template, sync it with a Discourse with live refresh, and update any changes using your editor. It’s much easier than using the UI!

2 Likes

Thank you so much - it knew there was something I was missing - I will definitely set it up to use the theme cli and edit them that way :slight_smile: :slight_smile:

1 Like

Thanks again Arkshine, I created my first component using discourse_theme now :slight_smile:
For anyone finding this thread, I basically just had to run a few commands:

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

then edit the file: javascripts/discourse/api-initializers/.js
upload it to github, and you can install / share.
Mine is here.
It appears to have a feature where you can automatically update the version on your server as well, as you modify files. Sounds good, and useful as I get into more complex components.

Cheers

1 Like