External jQuery conflict in page summary content in Moodle 3.6

External jQuery conflict in page summary content in Moodle 3.6

by Kamran Akram -
Number of replies: 5

Hi,

We are using javascript (jQuery) in page summary content, like screenshot below.

A screenshot of how we are using code in page content


Our current version is 3.3, but after upgrading to 3.6, the above js code does not work, because external jQuery conflicts with Moodle's jQuery and all the initializations on our jQuery does not execute at all. We have tons of pages to update and a huge production userbase so we are hesitating to make any change this big. Is there any way to make it work with some quick changes in Moodle's functionality?


We have tried the following code and it works, but like I said this will be a really huge change.


function initScript(libraries = [], callback, requireJQuery = true){
    if (!callback)
        callback = function () {};
    var jRef;
    var oldJquery = false;
    if(requireJQuery){
        if($ !== undefined)
            oldJquery = true;
        else
            includeJquery();
    }
    for (i=0; i<libraries.length; i++) {
        includeJS(libraries[i]);
    }
    if(requireJQuery){
        if(!oldJquery)
            jRef = $.noConflict(true);
        else
            jRef = $;
        callback(jRef);
    } else {
        callback(null);
    }
}

This code works fine by calling via summary content like this



    var urls = ['/local/3rdMil/javascript/LoadingOverlay.js'];
    initScript(urls, function (_$) {
        _$.LoadingOverlay('show');
        _$(document).ready(function () {
          .
          .
          .

A quick help will be very much appreciated.

Average of ratings: -
In reply to Kamran Akram

Re: External jQuery conflict in page summary content in Moodle 3.6

by Martin Greenaway -

Your attempt to include a new version of jQuery is probably being stripped, because Moodle wants javascript to be included from AMD Modules instead of read in from external scripts.

You can see more about Moodle's use of Javascript Modules here: https://docs.moodle.org/dev/Javascript_Modules

There's also some jQuery-specific stuff in Moodle docs here: https://docs.moodle.org/dev/jQuery


In reply to Martin Greenaway

Re: External jQuery conflict in page summary content in Moodle 3.6

by Kamran Akram -

My jQuery is not being stripped, it loads fine and initialize all the jQuery dependent code but then when Moodle's requirejs is loaded in footer and requirejs loads its own jQuery, then all the old initializations don't work anymore as "$" is replaced with the latest loaded jQuery reference.


It is really difficult to convert 500+ pages to use js modules, it requires a lot of resources, time and testing.

And js modules are there from version 2.9 but our jQuery code is still working fine till Moodle 3.5.

There is something changed in version 3.6 which is causing the problem.

I'm trying to find the possible change in JS workflow in Moodle 3.6, it would be really helpful if you or anyone can identify the change.

Thank you

In reply to Kamran Akram

Re: External jQuery conflict in page summary content in Moodle 3.6

by Martin Greenaway -

Ah - then this sounds like something more complex than I can help with I'm afraid, sorry.

In reply to Kamran Akram

Re: External jQuery conflict in page summary content in Moodle 3.6

by Darko Miletić -

Is there really a need to use external jQuery? For javascript code that requires jQuery to be loaded in classic manner you can just add this to your page code:

require(__DIR__.'/config.php');
require_login();

$PAGE->set_context(context_system::instance());
$PAGE->set_url('/frit.php');
$PAGE->set_title('Test');

// load jQuery in the classic way
$PAGE->requires->jquery();

// Load jQuery UI in a classic way
$PAGE->requires->jquery_plugin('ui');
$PAGE->requires->jquery_plugin('ui-css');

$PAGE->requires->js('
// some js code
');

/** @var core_renderer $OUTPUT */
$OUTPUT;

echo $OUTPUT->header();

echo $OUTPUT->footer();


In reply to Kamran Akram

Re: External jQuery conflict in page summary content in Moodle 3.6

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

The problem is caused because you add a plugin(loadingoverlay) to jquery in the global space. And then Moodle comes along and re-loads jquery into that space and all your hardwork is lost. 

If you want this to work you need to delay the loading of your script until Moodle has loaded jquery. Pretty much as your code does. 

Though its not your preferred quick fix solution, I will suggest my own solution which can certainly solve this issue, and will be much more robust into the future. 

  1. Use the Generico filter https://moodle.org/plugins/filter_generico
    (and Atto plugin if you wish)
  2. Creating a "loadingoverlay" Generico template
  3. Add template filter strings to each of your page summaries, probably: {GENERICO:type=loadingoverlay}

This has two main benefits for you. Firstly you will not run into jquery problems because Generico creates AMD modules on the fly from your javascript. Secondly you can manage all the loading overlay logic from a single place. If you need to change it, you just have to do so in one place , and it will be reflected throughout the site.

These two templates demonstrate the addition of JQuery plugins. They are both presets included with the Generico filter. So to view the template code just install Generico and create a template from the appropriate preset.

AMD compatible: Codebox: https://moodle.org/plugins/view.php?id=2097

Not AMD compatible: Lightbox2:  https://moodle.org/plugins/view.php?id=2099