Guide to adding third party jQuery for AMD

Jump to: navigation, search

Introduction

Since Moodle 2.9, Java-script AMD modules are best practice for inserting Java-script in Moodle plugins. Finding it hard to find good documentation, I decided to share the steps I used to add third party jQuery libraries to my plugin. There may be other ways to do this, however, this is the way I found that worked for my projects. Throughout this tutorial, I will be referring to the jQuery plugin called FullCalendar. I use FullCalender for a local plugin called writingcentre that I developed for Moodle 2.8. I needed to upgrade the plugin for Moodle 3.5 and figured I should use the new AMD model to add the java-script.

Create the folder structure

Although you can use any folder structure you like, this is my preferred way of laying out my folder structure.

  1. You must create an amd folder with two subfolders: src and build.
  2. Create a js folder. This folder will contain all third party jQuery/Java-scripts
  3. Download the jQuery plugin and extract/copy it to your js folder.

The folder structure should be similar to the image below.

caption

Configure the shim file

We need a file to configure requirejs so that the third party java-scripts can be used throughout our plugin.

In the amd->src folder create a file called config.js. Note that you can call this file what ever you want. Just remember that you will need to refer to it in later steps.

Enter the following code into the file

define([], function () {
    window.requirejs.config({
        paths: {
           //Enter the paths to your required java-script files  
        },
        shim: {
           //Enter the "names" that will be used to refer to your libraries
        }
    });
});

In the case of FullCalendar, there are two java-script files required for the plugin to work. Add the path to the two files within the paths array and then add the name to refer to these files in the shim array.
M.cfg.wwwroot is a java-script function provided by Moodle that returns the url of your site.
Note: You must enter the paths and shim in the order that the files must load. In this case, moment.js must load before fullcalendar.js
The final code looks like this.

define([], function () {
    window.requirejs.config({
        paths: {
            "moment": M.cfg.wwwroot + '/local/writingcentre/js/fullcalendar-3.9.0/lib/moment.min',
            "fullcalendar": M.cfg.wwwroot + '/local/writingcentre/js/fullcalendar-3.9.0/fullcalendar.min',
        },
        shim: {
            'moment': {exports: 'moment'},
            'fullcalendar': {exports: 'fullCalendar'},
        }
    });
});

File definitions

You must now define the third party files as AMD. For each shim in your configuration file, create a java-script file in the amd->src folder. In the above case, we would create two files: moment.js and fullcalendar.js Within each file, you will enter the following code.

define(['your_plugin_type_and_name'/'name_of_your_config_file', 'shim_name'], function(unused,shim_export_value) {
      return shim_export_value;
   }
);

Here is an example of the moment file.

define(['local_writingcentre/config', 'moment'], function(unused,moment) {
      return moment;
   }
);

and the fullcalender.js file

define(['local_writingcentre/config', 'fullcalendar'], function(unused,fullCalendar) {
      return fullCalendar;
   }
);

Using your third party plugins in your custom java-script

So now that all is configured, you need to be able to use these third party plugins in your java-script files.
Let's start by creating a java-script file. In this case, it is the code for managing the writingcentre. So let's call the file manage.js.
This file must always start by defining the java-script that you require. In this case, we require jQuery, jQueryUI, moment and fullCalendar. I also add a variable wwwroot that I will use throughout the script. Note that this is not required, but it is my preferred way of working.
For more information on what is required in this file, refer to Javascript Modules
Your file should look like the code below.

define(['jquery', 'jqueryui', 'local_writingcentre/moment', 'local_writingcentre/fullcalendar'], function ($, jqui, moment, fullCalendar) {
var wwwroot = M.cfg.wwwroot;
 
    function initManage() {
       //Do your java-script magic here
    }
 
    return {
        init: function () {
            initManage();
        }
    };
});

Now you are ready to use the third party libraries. Here is a sample of how I used fullCalendar. Note that this is not the complete java-script file, only a small portion of the code.

define(['jquery', 'jqueryui', 'local_writingcentre/moment', 'local_writingcentre/fullcalendar'], function ($, jqui, moment, fullCalendar) {
var wwwroot = M.cfg.wwwroot;
 
    function initManage() {
       $('#calendar').fullCalendar({
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'agendaWeek,agendaDay'
            },
            businessHours: {
                start: opentime, // a start time (10am in this example)
                end: closetime, // an end time (6pm in this example)
            },
            handleWindowResize: true,
            contentHeight: 'auto',
            minTime: opentime + ':00',
            maxTime: closetime + ':00',
            slotDuration: '00:10:00',
            slotEventOverlap: true,
            events: 
                {
                    url: wwwroot + '/local/writingcentre/events.php?servicetype=' + serviceType,
                    type: 'POST',
                    data: function () {
                        var fecha = $('#calendar').fullCalendar('getDate');
                        return {
                            month: fecha.format("MM"),
                            year: fecha.format("YYYY")
                        }
                    },
                    error: function(err) {
                        console.log(err);
                        alert('An error occured trying to retrieve the calendar events');
 
                    }
                },
 
            weekends: false,
            defaultView: 'agendaWeek',
            dayClick: function (date, jsEvent, view) {
                var hour = date.format('HHmm');
                var alldaydate = date.format('YYYYMMDD');
                if ($('#allday-' + alldaydate).val() != 'true') {
                    window.location.href = wwwroot + "/local/writingcentre/appointment.php?defaultdate=" + date.format() + "&servicetype=" + serviceType;
                } else {
                    alert('It is not passible to book an appointment on this day. Please select another time');
                }
 
            },
            eventClick: function (event) {
                var appointment = '';
                if (event.firstvisit) {
                    appointment = event.title + "<br>" +
                            event.start.format('YYYY-MM-DD HH:mm') + "<br>" +
                            "Remaining seats: " + event.remaining + "<br>" +
                            "Registered users: <br>" +
                            event.registeredusers;
 
                    $('#dialog_content').html(appointment);
                    $('#dialog').dialog({
                        resizable: false,
                        width: 600,
                        height: 'auto',
                        modal: true,
                        buttons: [
                            {
                                text: "Ok",
                                class: "btn btn-default",
                                click: function () {
                                    $(this).dialog("close");
                                }
                            },
                            {
                                text: "Delete",
                                class: "btn btn-danger",
                                click: function () {
                                    $(this).dialog("close");
                                    $('#delete').dialog({
                                        resizable: false,
                                        height: 400,
                                        modal: true,
                                        buttons: [
                                            {
                                                text: "Confirm",
                                                class: "btn btn-danger",
                                                click: function () {
                                                    delete_event(event.id, wwwroot);
                                                    $(this).dialog("close");
                                                }
                                            },
                                            {
                                                text: "Cancel",
                                                class: "btn btn-warning",
                                                click: function () {
                                                    $(this).dialog("close");
                                                }
                                            }
                                        ]
 
                                    });
                                }
                            }
                        ]
                    });
                } else if (event.event == 'true') {
                    if (event.closed == 1) {
                        alert('Sorry the Writing centre is closed during this time.')
                    } else {
                        appointment = event.title + "<br>" +
                                event.start.format('YYYY-MM-DD HH:mm') + "<br>" +
                                "<br>Remaing seats: " + event.remaining;
                        $('#dialog_content').html(appointment);
                        $('#dialog').dialog({
                            resizable: false,
                            width: 600,
                            height: 300,
                            modal: true,
                            buttons: {
                                "Register": function () {
                                    if (event.remaining == 0) {
                                        alert('Sorry, this is event is full');
                                    } else {
                                        $.ajax({
                                            url: "register.php?id=" + event.id,
                                            dataType: "text",
                                            success: function (result) {
                                                alert(result);
                                                window.location.href = wwwroot + "/local/writingcentre/index.php?defaultdate=" + event.start.format('YYYY-MM-DD HH:mm');
                                            }
                                        });
                                    }
                                },
                                "Close": function () {
                                    $(this).dialog("close");
 
                                }
                            }
                        });
                    }
                }
            }
        });
    }
 
    return {
        init: function () {
            initManage();
        }
    };
});

##IMPORTANT## Remember, in order for your java-script to work, you must use grunt to compile your java-script and you must include your java-script in your templates or php files. For more information on how to do so, see the section "Including an external javascript/jquery library" at Javascript Modules

But wait! The CSS is not loaded

The above steps only load the java-script. If your third party plugin also has CSS, you must load the CSS using $PAGE->requires->css in php. Here is how I added the CSS for fullCalendar.

$PAGE->requires->css('/local/writingcentre/js/fullcalendar-3.9.0/fullcalendar.min.css', true);

Note: While working on this plugin, I noticed that jQueryUI css was not loading, so I downloaded jQueryUI and added the css to my plugin.

$PAGE->requires->css('/local/writingcentre/css/jquery-ui.min.css');