Moodle 4 jQuery script works, but not in courseindex drawer

Moodle 4 jQuery script works, but not in courseindex drawer

by Andreas Giesen -
Number of replies: 4
I added a jQuery script file to the theme's /javascript - folder and the resp. line (javascripts_footer) in the theme's config.php´

It works for the most part - it is supposed to find a string within the names of activities and when found, remove that string. This works everywhere (like breadcrumb, activity-page-title etc.), except in the courseindex-drawer. I suspect, that the drawer populates after the custom script is already done. 

This is only part of the script - the enclosing function is called for a list of shortcodes ("text")

  // Remove shortcode: page caption > WORKS
  $('#page-header H1').contents().each(function(_, node) {
    if (node.nodeValue && node.nodeValue.includes(text)) {
      node.nodeValue = node.nodeValue.replace(text, "");
    }
  })
  // Remove shortcode: breadcrumb > WORKS
  $('.breadcrumb span').contents().each(function(_, node) {
    if (node.nodeValue && node.nodeValue.includes(text)) {
      node.nodeValue = node.nodeValue.replace(text, "");
    }
  })
  // Remove shortcode: courseindex-link > DOES NOT WORK
  $('.courseindex-link').contents().each(function(_, node) {
    if (node.nodeValue && node.nodeValue.includes(text)) {
      node.nodeValue = node.nodeValue.replace(text, "");
    }
  })

Is there any way to make this work in the drawer as well? 

Average of ratings: -
In reply to Andreas Giesen

Re: Moodle 4 jQuery script works, but not in courseindex drawer

by Ferran Recio Calderó -
Picture of Core developers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
Hi Andreas,

The course index is loaded async after the page is fully loaded. That is the reason why you cannot modify it with the jQuery "ready" method. However, there are a few things you need to know before interacting with the course index.

The course index is a reactive component. The placeholder just renders a mustache template using the data from a data structure called "state". All frontend logic in 4.0+ courses is reactive to this "state" data, meaning that if that structures change at any time, the reactive component will recalculate parts of the frontend immediately. In general, touching the HTML of a reactive element from outside a reactive component itself is not advised as it will be reloaded at any moment.

Furthermore, the course index uses the browser's local storage to cache the HTML and JS. This means most times the content can be loaded directly from the browser, without loading any extra mustache template.

If you want to alter the HTML from the course index you have some options:
- If you have a custom theme, you can override any of the core_courseformat/local/courseindex/* templates (for example, to alter the activity element, you can modify the course/format/templates/local/courseindex/cm.mustache file)
- If you are developing a course format, you can add custom information to the state data and also provide alternative mustache files. (more documentation here: https://moodledev.io/docs/apis/plugintypes/format#format-output-classes-and-templates ) or even replace the full course index by overriding the course_index_drawer renderer method.
- If you are developing a theme, you can integrate an AMD module with the reactive course editorand implement your own reactive component (reactive documentation: https://moodledev.io/docs/guides/javascript/reactive ).
- You can even combine some of the points below and provide an alternative core_courseformat/local/courseindex/courseindex template that load and overrides version of th the core_courseformat/local/courseindex/courseindex AMD module to extend the original logic.

However, if you still want to interact directly with a reactive element HTML (which is not recommended at all), you can import the getCurrentCourseEditor from 'core_courseformat/courseeditor' and the use the state ready promise doing getCurrentCourseEditor().getInitialStatePromise().then(...)

I hope this helps,

Ferran.
In reply to Ferran Recio Calderó

Re: Moodle 4 jQuery script works, but not in courseindex drawer

by Andreas Giesen -
Thanks for the info... I think the first 4 options would not work for what I am trying to do.

Maybe I need to explain, what I am trying to do: Often the activity-icons don't match the actual content or are not specific. Two examples: a text page that embeds a video from Vimeo should have a video icon. Or especially H5P activities all get the same h5p-icon no matter what kind of activity it actually is.

The jQuery reads the activity-title and looks for a shortcode that triggers an exchange of the icon. Of course I don't want the shortcode to actually appear in the text, so next I remove it from the title. This method gives editing teachers a method to assign any available icon to any activity or resource simply by placing a shortcode into the title. 

In Boost 3.X this worked nicely, there are about 4 or 5 places where the text needs to be removed and 3 or 4 places, where the icon needs to be replaced.

Now I changed the jQuery to do the same in Boost 4 and am left with only that one place where it does not work. Would the method with getCurrentCourseEditor work for that scenario? (I'd still need to figure out, what exactly I would need to do there, but it sounds like it could work...)
In reply to Ferran Recio Calderó

Re: Moodle 4 jQuery script works, but not in courseindex drawer

by Andreas Giesen -
> However, if you still want to interact directly with a reactive element HTML (which is not recommended at all), you can import the getCurrentCourseEditor from 'core_courseformat/courseeditor' and the use the state ready promise doing getCurrentCourseEditor().getInitialStatePromise().then(...)

How and where do I import the "getCurrentCourseEditor" so it is available in the javascript? I tried adding it in the mustache template in the JS-Section, but it needs to be "inside a module". I tried calling the import inside a function(module) but "getCurrentCourseEditor" is not available / defined. Can so. help with this?
In reply to Andreas Giesen

Re: Moodle 4 jQuery script works, but not in courseindex drawer

by Ferran Recio Calderó -
Picture of Core developers Picture of Moodle HQ Picture of Peer reviewers Picture of Plugin developers Picture of Testers
It doe snot need to be inside a module. You just need to require the module inside the {{#js}} section of your mustache file:

{{#js}}
require(['core_courseformat/local/courseeditor'], function(editor) {
const currentCourse = editor.getCurrentCourseEditor();
});
{{/js}}