Merge branch 'MDL-57682-master-fix' of git://github.com/andrewnicols/moodle
[moodle.git] / media / player / videojs / amd / src / loader.js
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16 /**
17  * Video JS loader.
18  *
19  * This takes care of applying the filter on content which was dynamically loaded.
20  *
21  * @module     media_videojs/loader
22  * @package    media_videojs
23  * @copyright  2016 Frédéric Massart - FMCorz.net
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 import Config from 'core/config';
28 import Event from 'core/event';
29 import jQuery from 'jquery';
30 import Ajax from 'core/ajax';
31 import LocalStorage from 'core/localstorage';
32 import Notification from 'core/notification';
34 /** @var {bool} Whether this is the first load of videojs module */
35 let firstLoad;
37 /** @var {string} The language that is used in the player */
38 let language;
40 /** @var {object} List of languages and translations for the current page */
41 let langStringCache;
43 /**
44  * Set-up.
45  *
46  * Adds the listener for the event to then notify video.js.
47  * @param {string} lang Language to be used in the player
48  */
49 export const setUp = (lang) => {
50     language = lang;
51     firstLoad = true;
52     // Notify Video.js about the nodes already present on the page.
53     notifyVideoJS(null, jQuery('body'));
54     // We need to call popover automatically if nodes are added to the page later.
55     Event.getLegacyEvents().done((events) => {
56         jQuery(document).on(events.FILTER_CONTENT_UPDATED, notifyVideoJS);
57     });
58 };
60 /**
61  * Notify video.js of new nodes.
62  *
63  * @param {Event} e The event.
64  * @param {NodeList} nodes List of new nodes.
65  */
66 const notifyVideoJS = (e, nodes) => {
67     const selector = '.mediaplugin_videojs';
68     const langStrings = getLanguageJson();
70     // Find the descendants matching the expected parent of the audio and video
71     // tags. Then also addBack the nodes matching the same selector. Finally,
72     // we find the audio and video tags contained in those parents. Kind thanks
73     // to jQuery for the simplicity.
74     nodes.find(selector)
75         .addBack(selector)
76         .find('audio, video').each((index, element) => {
77             const id = jQuery(element).attr('id');
78             const config = jQuery(element).data('setup-lazy');
79             const modulePromises = [import('media_videojs/video-lazy')];
81             if (config.techOrder && config.techOrder.indexOf('youtube') !== -1) {
82                 // Add YouTube to the list of modules we require.
83                 modulePromises.push(import('media_videojs/Youtube-lazy'));
84             }
85             if (config.techOrder && config.techOrder.indexOf('flash') !== -1) {
86                 // Add Flash to the list of modules we require.
87                 modulePromises.push(import('media_videojs/videojs-flash-lazy'));
88             }
89             Promise.all([langStrings, ...modulePromises])
90             .then(([langJson, videojs]) => {
91                 if (firstLoad) {
92                     videojs.options.flash.swf = `${Config.wwwroot}/media/player/videojs/videojs/video-js.swf`;
93                     videojs.addLanguage(language, langJson);
95                     firstLoad = false;
96                 }
97                 videojs(id, config);
98                 return;
99             })
100             .catch(Notification.exception);
101         });
102 };
104 /**
105  * Returns the json object of the language strings to be used in the player.
106  *
107  * @returns {Promise}
108  */
109 const getLanguageJson = () => {
110     if (langStringCache) {
111         return Promise.resolve(langStringCache);
112     }
114     const cacheKey = `media_videojs/${language}`;
116     const rawCacheContent = LocalStorage.get(cacheKey);
117     if (rawCacheContent) {
118         const cacheContent = JSON.parse(rawCacheContent);
120         langStringCache = cacheContent;
122         return Promise.resolve(langStringCache);
123     }
125     const request = {
126         methodname: 'media_videojs_get_language',
127         args: {
128             lang: language,
129         },
130     };
132     return Ajax.call([request])[0]
133         .then(langStringData => {
134             LocalStorage.set(cacheKey, langStringData);
136             return langStringData;
137         })
138         .then(result => JSON.parse(result))
139         .then(langStrings => {
140             langStringCache = langStrings;
142             return langStrings;
143         });
144 };