What controls the order of execution for Theme components' j/s?

I have j/s in my theme (am I infamous yet? ;) which is modifying the DOM by adding elements via api.decorateCooked(…. It inserts a variety HTML head elements.

I also have the DiscoTOC Theme component installed.

However, adding the usual <div data-theme-toc="true"> </div> that DiscoTOC notices and expands, doesn’t generate a table-of-contents including my dynamically inserted elements.

I’m figuring this might be as simple as execution order… if DiscoTOC looks before my j/s adds more elements . . .

What determines the ordering of execution if multiple bits of theme j/s code are calling api.cooked(?

3 Likes

bump? :slight_smile:

plus silliness to get to 20 characters

Note that DiscoTOC only runs on post contents - if you’re inserting those elements outside posts, it won’t see them.

I don’t think we’ve needed to define JS execution order yet.

1 Like

I’m inserting within the post, yes. That’s why I suspect execution order.

Some bit of code determines the execution order… that’s the leverage point for me to get my component before TOC. eg, if it’s alpha by component name (ie, as displayed in the Component list in Admin area) then I can try namin my component accordingly, etc

Pretty sure that the component execution order is not based on the name of the component. It’s based on the ID by default.

That said, you can set initializer order for advanced use cases. I can put DiscoTOC in a named initializer so you can run your code before DiscoTOC, but I need to know what you’re trying to do first to give you a clear answer.

Your modifications here are based on an HTTP/AJAX request, correct?

1 Like

Yes AJAX, but using a synchronous call. (I’ve always loved the oxymoron of synchronous AJAX :^)

I’m feeling like my next step is create a proper component—atm, it’s just some j/s pasted into my Theme’s Header. Then I can try fiddling with a judiciously chosen ID. “_foo” or “0-foo” might be all I need.

1 Like

Don’t we all :wink:

Correct. If you want to use named initializers and initializer order, your component will need to have an initializer in the /javascript folder.

No worries, though. I can help with all of that. I’ll get back to you on this tomorrow with a full answer.

1 Like

A while ago, I turned my j/s hacking into a proper theme component.

I’d love to circle back to getting the ordering be such that my component runs before Discourse table-of-contents.

iirc, Theme Components are evaluated after plugins.

And could be wrong, but they are loaded in order of name, so putting an x- in front of the name has in the past helped me ensure a specific Theme Component is evaluated last.

That’s fine. I’m trying to wrangle the order of the DiscoTOC ( https://github.com/discourse/DiscoTOC.git ) component and a component of my own creation.

Replies by others above suggest the name of the component does not affect the execution order. I’ve just renamed them to be aa-mycomponent and x-last-DiscoTOC and it doesn’t work. [DiscoTOC doesn’t include headings added to the DOM dynamically—yes, within the post body]

@Johani any further ideas from your May train of thought?

hmmmmmmm… maybe what’s wrong is more than ordering. I just hit inspect… and the things in the DOM which I thought where HTML headings… are in fact DIV tags with class="d-toc-ignore"

Time for me to dig further. Where’d my headings go? :slight_smile:

Well, I think you could prove that out either way by trying a very basic example.

Create two simple components, overriding or connecting the same thing, perhaps a simple template with a slight difference, call one by a name starting later in the alphabet, note which one ends up overriding the theme.

It’s very clearly ordered by name in the code here in the model:

1 Like

The Name doesn’t affect execution order. @merefield the line you linked affects how they’re displayed in the admin UI, but isn’t used for the actual execution.

This is the relevant line for execution order:

So they are executed in ascending order of ‘id’ in the database.

The only guarantee that’s portable across Discourse instances is that theme code is always executed before theme component code.

As @Johani mentioned above, if you have need to run code after some other component has loaded, the best bet is probably to use an Ember initializer, which supports ordering. Unfortunately that won’t be possible straight away in this case, since it doesn’t look like DiscoTOC is using Ember initializers. Updating DiscoTOC to use multi-file javascript (and therefore ember initializers) would certainly be #pr-welcome

3 Likes

That’s unfortunate because might be useful. Thanks for clarifying in any case!

1 Like

(…and, this is related to Theme component order of precedence )

Just circling back to say that the DB ID order of precedence does work; Solves my need. Thanks all!

2 Likes