Guide to adding third party jQuery for AMD
Step by step guide to adding third party jQuery for AMD
Since Moodle 2.9, Java-script AMD modules are best practice for inserting Java-script in Moodle plugins. Here are the steps required to add third party jQuery libraries. Note that 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.
- You must create an amd folder with two subfolders: src and build.
- Create a js folder. This folder will contain all third party jQuery/Java-scripts
- Download the jQuery plugin and extract/copy it to your js folder.
The folder structure should be similar to the image below.
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 + "
" +
event.start.format('YYYY-MM-DD HH:mm') + "
" +
"Remaining seats: " + event.remaining + "
" +
"Registered users:
" +
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 + "
" +
event.start.format('YYYY-MM-DD HH:mm') + "
" +
"
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();
}
};
}
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 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. 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');