@oat-sa/tao-core-ui 1.6.2 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ define(function () { 'use strict';
2
+
3
+ /**
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License
6
+ * as published by the Free Software Foundation; under version 2
7
+ * of the License (non-upgradable).
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ *
18
+ * Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
19
+ */
20
+
21
+ /**
22
+ * Creates a reminder manager.
23
+ *
24
+ * A reminder manager allows to register callback functions that will be called after a particular amount of time.
25
+ * The schedule can be created and cancelled at any time.
26
+ *
27
+ * @example
28
+ * // Create a reminder manager
29
+ * const manager = reminderManagerFactory();
30
+ *
31
+ * // Add a reminder that will be called after 2s (delay is given in milliseconds)
32
+ * manager.remind(() => console.log('Hello!'), 2000);
33
+ *
34
+ * // Start the schedule
35
+ * manager.start();
36
+ *
37
+ * // We can know how many time elapsed since the last schedule
38
+ * const elapsed = manager.elapsed;
39
+ *
40
+ * // The schedule can be cancelled
41
+ * if (needToCancel) {
42
+ * manager.stop();
43
+ * }
44
+ *
45
+ * // The schedule should be cancelled
46
+ * console.log('schedule running:', manager.running)
47
+ *
48
+ * @returns {reminderManager}
49
+ */
50
+ function reminderManagerFactory() {
51
+ // Keep track of the running state
52
+ var running = false; // Timestamp of the last start
53
+
54
+ var last = 0; // A list of reminders to callback
55
+
56
+ var reminders = new Map();
57
+ /**
58
+ * Cancels a schedule for a particular reminder.
59
+ * @param {object} state - A sate object containing the timeout handler for the reminder.
60
+ * @private
61
+ */
62
+
63
+ var stopReminder = function stopReminder(state) {
64
+ if (state && state.timeout) {
65
+ clearTimeout(state.timeout);
66
+ state.timeout = null;
67
+ }
68
+ };
69
+ /**
70
+ * Cancel the schedule for all reminders.
71
+ * @private
72
+ */
73
+
74
+
75
+ var stopAllReminders = function stopAllReminders() {
76
+ return reminders.forEach(stopReminder);
77
+ };
78
+ /**
79
+ * Schedule all reminders.
80
+ * @private
81
+ */
82
+
83
+
84
+ var startAllReminders = function startAllReminders() {
85
+ reminders.forEach(function (state, reminder) {
86
+ stopReminder(state);
87
+ state.timeout = setTimeout(reminder, state.delay);
88
+ });
89
+ };
90
+ /**
91
+ * Defines the API of a reminder manager.
92
+ *
93
+ * A reminder manager allows to register callback functions that will be called after a particular amount of time.
94
+ * The schedule can be created and cancelled at any time.
95
+ *
96
+ * @namespace reminderManager
97
+ */
98
+
99
+
100
+ return {
101
+ /**
102
+ * Tells whether or not the schedule is running.
103
+ * @type {boolean}
104
+ * @member running
105
+ * @memberOf reminderManager
106
+ */
107
+ get running() {
108
+ return running;
109
+ },
110
+
111
+ /**
112
+ * Gives the amount of time elapsed since the start of the schedule. It is given in milliseconds.
113
+ * If the schedule is not running, it will always be 0.
114
+ * @type {number}
115
+ * @member running
116
+ * @memberOf reminderManager
117
+ */
118
+ get elapsed() {
119
+ if (!running) {
120
+ return 0;
121
+ }
122
+
123
+ return performance.now() - last;
124
+ },
125
+
126
+ /**
127
+ * Schedules all reminders from now on.
128
+ *
129
+ * @returns {reminderManager}
130
+ * @function start
131
+ * @memberOf reminderManager
132
+ */
133
+ start: function start() {
134
+ running = true;
135
+ last = performance.now();
136
+ startAllReminders();
137
+ return this;
138
+ },
139
+
140
+ /**
141
+ * Cancels all scheduled reminders.
142
+ *
143
+ * @returns {reminderManager}
144
+ * @function stop
145
+ * @memberOf reminderManager
146
+ */
147
+ stop: function stop() {
148
+ running = false;
149
+ stopAllReminders();
150
+ return this;
151
+ },
152
+
153
+ /**
154
+ * Adds a callback to be scheduled.
155
+ * It won't be scheduled until the schedule is restarted.
156
+ *
157
+ * @param {Function} cb - A function to call after the delay elapsed.
158
+ * @param {number} delay - The delay after what call back the reminder. It is given in milliseconds.
159
+ * @returns {reminderManager}
160
+ * @function remind
161
+ * @memberOf reminderManager
162
+ */
163
+ remind: function remind(cb, delay) {
164
+ if ('function' === typeof cb && delay) {
165
+ stopReminder(reminders.get(cb));
166
+ reminders.set(cb, {
167
+ delay: delay
168
+ });
169
+ }
170
+
171
+ return this;
172
+ },
173
+
174
+ /**
175
+ * Removes a scheduled callback. If a schedule was running, it will be cancelled first.
176
+ *
177
+ * @param {Function} [cb] - The callback function to remove. If omitted, all reminders will be removed.
178
+ * @returns {reminderManager}
179
+ * @function forget
180
+ * @memberOf reminderManager
181
+ */
182
+ forget: function forget(cb) {
183
+ if ('undefined' !== typeof cb) {
184
+ stopReminder(reminders.get(cb));
185
+ reminders.delete(cb);
186
+ } else {
187
+ stopAllReminders();
188
+ reminders.clear();
189
+ }
190
+
191
+ return this;
192
+ }
193
+ };
194
+ }
195
+
196
+ return reminderManagerFactory;
197
+
198
+ });
@@ -0,0 +1,149 @@
1
+ define(['core/eventifier'], function (eventifier) { 'use strict';
2
+
3
+ eventifier = eventifier && eventifier.hasOwnProperty('default') ? eventifier['default'] : eventifier;
4
+
5
+ /**
6
+ * This program is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU General Public License
8
+ * as published by the Free Software Foundation; under version 2
9
+ * of the License (non-upgradable).
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ *
20
+ * Copyright (c) 2021 (original work) Open Assessment Technologies SA ;
21
+ */
22
+ /**
23
+ * Creates a time observer.
24
+ *
25
+ * It observes the updates applied to a timeline, raising a flag when an irregularity occurs.
26
+ *
27
+ * It works as follow:
28
+ * - an initial state is defined (example: current: 0, duration: 100)
29
+ * - each time a position is forced (say the position is changed outside of the regular time update), the observer needs
30
+ * to be notified.
31
+ * - each time the position is updated (say regular time update), the observer needs to be called.
32
+ * - if the difference between the last regular update and the last one is too high, an event is triggered
33
+ *
34
+ * @example
35
+ * // Create a time observer with an expected interval of 2 seconds
36
+ * const observer = timeObserverFactory(2);
37
+ *
38
+ * // Init the state
39
+ * observer.start(player.position, player.duration);
40
+ *
41
+ * // Update on a regular basis
42
+ * player.on('timeupdate', () => observer.update(player.position));
43
+ *
44
+ * // Notify any position change outside of the regular update
45
+ * player.on('seek', () => observer.seek(player.position));
46
+ *
47
+ * // Gets informed from any irregularity
48
+ * observer.on('irregularity', () => console.log('irregular jump in time');
49
+ *
50
+ * @param {number} interval - The typical interval expected between two updates. It is given in seconds.
51
+ * @returns {timeObserver}
52
+ */
53
+
54
+ function timeObserverFactory() {
55
+ var interval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
56
+ // Current time position
57
+ var position = 0; // Total duration expected
58
+
59
+ var duration = 0; // Last position forced
60
+
61
+ var _seek = 0;
62
+ /**
63
+ * Defines the API of a time observer.
64
+ *
65
+ * It observes the updates applied to a timeline, raising a flag when an irregularity occurs.
66
+ *
67
+ * @namespace timeObserver
68
+ */
69
+
70
+ return eventifier({
71
+ /**
72
+ * Gets the current time position reported to the observer.
73
+ *
74
+ * @returns {number}
75
+ * @type {number}
76
+ * @member position
77
+ * @memberOf timeObserver
78
+ */
79
+ get position() {
80
+ return position;
81
+ },
82
+
83
+ /**
84
+ * Gets the total duration reported to the observer.
85
+ *
86
+ * @returns {number}
87
+ * @type {number}
88
+ * @member duration
89
+ * @memberOf timeObserver
90
+ */
91
+ get duration() {
92
+ return duration;
93
+ },
94
+
95
+ /**
96
+ * Initialises the time state.
97
+ *
98
+ * @param {number} initPosition - The initial time position
99
+ * @param {number} initDuration - The total duration expected
100
+ * @returns {timeObserver}
101
+ * @function init
102
+ * @memberOf timeObserver
103
+ */
104
+ init: function init(initPosition, initDuration) {
105
+ position = _seek = initPosition;
106
+ duration = initDuration;
107
+ return this;
108
+ },
109
+
110
+ /**
111
+ * Updates the time position. If the difference with the previous update is too high, an `irregularity` event
112
+ * will be emitted.
113
+ *
114
+ * @param {number} newPosition - The new time position
115
+ * @returns {timeObserver}
116
+ *
117
+ * @fires irregularity
118
+ */
119
+ update: function update(newPosition) {
120
+ if (newPosition > _seek && newPosition - position > interval) {
121
+ /**
122
+ * Notifies an irregularity in the time update
123
+ * @event irregularity
124
+ * @param {number} position - last regular position
125
+ * @param {number} newPosition - new irregular position
126
+ */
127
+ this.trigger('irregularity', position, newPosition);
128
+ }
129
+
130
+ position = newPosition;
131
+ return this;
132
+ },
133
+
134
+ /**
135
+ * Notifies the observer about a change in the position outside of the regular update.
136
+ *
137
+ * @param {number} seekPosition
138
+ * @returns {timeObserver}
139
+ */
140
+ seek: function seek(seekPosition) {
141
+ position = _seek = seekPosition;
142
+ return this;
143
+ }
144
+ });
145
+ }
146
+
147
+ return timeObserverFactory;
148
+
149
+ });
@@ -146,7 +146,7 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
146
146
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Reload", options) : helperMissing.call(depth0, "__", "Reload", options)))
147
147
  + "\"></div>\n <div class=\"message\">"
148
148
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "You are encountering a prolonged connectivity loss.", options) : helperMissing.call(depth0, "__", "You are encountering a prolonged connectivity loss.", options)))
149
- + "</div>\n <div class=\"message\">"
149
+ + " "
150
150
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to reload.", options) : helperMissing.call(depth0, "__", "Click to reload.", options)))
151
151
  + "</div>\n </a>\n </div>\n </div>\n <div class=\"controls\">\n <div class=\"bar\">\n <div class=\"control actions playback\">\n <a class=\"action play\" data-control=\"play\" title=\""
152
152
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
@@ -236,7 +236,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
236
236
  startMuted: false,
237
237
  maxPlays: 0,
238
238
  replayTimeout: 0,
239
- stalledTimeout: 2000,
240
239
  canPause: true,
241
240
  canSeek: true,
242
241
  loop: false,
@@ -359,8 +358,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
359
358
  /**
360
359
  * Builds a media player instance
361
360
  * @param {Object} config
362
- * @param {String} config.type - The type of media to play
363
- * @param {String|Array} config.url - The URL to the media
361
+ * @param {String} config.type - The type of media to play, say `audio`, `video`, or `youtube`. The default is `video`.
362
+ * It might also contain the MIME type of the media as a shorthand.
363
+ * @param {String|Array} [config.url] - The URL to the media. If several media are proposed as alternatives,
364
+ * please look at the `sources` option instead.
365
+ * @param {String} [config.mimeType] - The MIME type of the media. If omitted, the player will try to extract it
366
+ * from the `type` property, otherwise it will request the server to get the content-type.
367
+ * @param {Array} [config.sources] - A list of URL if several media can be proposed. Each entry may be either a
368
+ * string (single URL), or an object containing both the URL and the MIME type ({src: string, type: string}).
364
369
  * @param {String|jQuery|HTMLElement} [config.renderTo] - An optional container in which renders the player
365
370
  * @param {Boolean} [config.canSeek] - The player allows to reach an arbitrary position within the media using the duration bar
366
371
  * @param {Boolean} [config.loop] - The media will be played continuously
@@ -370,15 +375,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
370
375
  * @param {Number} [config.autoStartAt] - The time position at which the player should start
371
376
  * @param {Number} [config.maxPlays] - Sets a few number of plays (default: infinite)
372
377
  * @param {Number} [config.replayTimeout] - disable the possibility to replay a media after this timeout, in seconds (default: 0)
373
- * @param {Number} [config.stalledTimeout] - delay before considering stalled playback (default: 2000)
374
378
  * @param {Number} [config.volume] - Sets the sound volume (default: 80)
375
379
  * @param {Number} [config.width] - Sets the width of the player (default: depends on media type)
376
380
  * @param {Number} [config.height] - Sets the height of the player (default: depends on media type)
377
381
  * @param {Boolean} [config.preview] - Enables the media preview (load media metadata)
378
382
  * @param {Boolean} [config.debug] - Enables the debug mode
383
+ * @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
379
384
  * @event render - Event triggered when the player is rendering
380
385
  * @event error - Event triggered when the player throws an unrecoverable error
381
- * @event recovererror - Event triggered when the player throws a recoverable error
382
386
  * @event ready - Event triggered when the player is fully ready
383
387
  * @event play - Event triggered when the playback is starting
384
388
  * @event update - Event triggered while the player is playing
@@ -411,6 +415,10 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
411
415
 
412
416
  _.defaults(this.config, defaults.options);
413
417
 
418
+ if (!this.config.mimeType && 'string' === typeof this.config.type && this.config.type.indexOf('/') > 0) {
419
+ this.config.mimeType = this.config.type;
420
+ }
421
+
414
422
  this._setType(this.config.type || defaults.type);
415
423
 
416
424
  this._reset();
@@ -538,26 +546,15 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
538
546
  * Triggers a reload event
539
547
  * @event mediaplayer#reload
540
548
  */
541
- this.trigger('reload'); // destroy player
549
+ this.trigger('reload');
542
550
 
543
551
  if (this.player) {
544
- this.player.destroy();
545
- } // remove events and component
546
-
547
-
548
- if (this.$component) {
549
- this._unbindEvents();
550
-
551
- this._destroySlider(this.$seekSlider);
552
-
553
- this._destroySlider(this.$volumeSlider);
554
-
555
- this.$component.remove();
556
- this.$component = null;
557
- } // rerender
552
+ this.player.recover();
553
+ }
558
554
 
555
+ this._setState('stalled', false);
559
556
 
560
- this.render();
557
+ this.setInitialStates();
561
558
  },
562
559
 
563
560
  /**
@@ -1002,8 +999,12 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1002
999
  source = _.clone(src);
1003
1000
  }
1004
1001
 
1005
- if (this.is('youtube') && !source.type) {
1006
- source.type = defaults.type;
1002
+ if (!source.type) {
1003
+ if (this.is('youtube')) {
1004
+ source.type = defaults.type;
1005
+ } else if (this.config.mimeType) {
1006
+ source.type = this.config.mimeType;
1007
+ }
1007
1008
  }
1008
1009
 
1009
1010
  if (!source.type) {
@@ -1093,7 +1094,8 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1093
1094
  type: this.getType(),
1094
1095
  sources: this.getSources(),
1095
1096
  preview: this.config.preview,
1096
- debug: this.config.debug
1097
+ debug: this.config.debug,
1098
+ stalledDetectionDelay: this.config.stalledDetectionDelay
1097
1099
  };
1098
1100
  this.player = playerFactory(this.$player, playerConfig).on('resize', function (width, height) {
1099
1101
  if (_this6.$component) {
@@ -1115,8 +1117,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1115
1117
  return _this6._onEnd();
1116
1118
  }).on('error', function () {
1117
1119
  return _this6._onError();
1118
- }).on('recovererror', function (fromLoading) {
1119
- return _this6._onRecoverError(fromLoading);
1120
1120
  });
1121
1121
  }
1122
1122
 
@@ -1135,7 +1135,13 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1135
1135
 
1136
1136
  this._setState('preview', this.config.preview);
1137
1137
 
1138
- this._setState('loading', true);
1138
+ this._setState('loading', !error);
1139
+
1140
+ if (error) {
1141
+ this._setState('ready', true);
1142
+
1143
+ this.trigger('ready');
1144
+ }
1139
1145
  },
1140
1146
 
1141
1147
  /**
@@ -1478,7 +1484,7 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1478
1484
  */
1479
1485
  _onReady: function _onReady() {
1480
1486
  if (this.is('error')) {
1481
- this._onRecoverError();
1487
+ this._setState('error', false);
1482
1488
  }
1483
1489
 
1484
1490
  var duration = this.player.getDuration();
@@ -1507,11 +1513,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1507
1513
 
1508
1514
  if (this.config.preview && this.$container && this.config.height && this.config.height !== 'auto') {
1509
1515
  this._setMaxHeight();
1510
- } // seek back to the previous position after recover from stalled
1511
-
1512
-
1513
- if (this.is('stalled')) {
1514
- this.play(this.positionBeforeStalled);
1515
1516
  }
1516
1517
  },
1517
1518
 
@@ -1585,29 +1586,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1585
1586
  this.trigger('error');
1586
1587
  },
1587
1588
 
1588
- /**
1589
- * Event called when the media throws recoverable error
1590
- * @param {Boolean} fromLoading - recover from an error while loading the media
1591
- * @private
1592
- */
1593
- _onRecoverError: function _onRecoverError() {
1594
- var fromLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
1595
-
1596
- // recover from playing error
1597
- if (fromLoading && this.is('playing')) {
1598
- this.render();
1599
- }
1600
-
1601
- this._setState('error', false);
1602
- /**
1603
- * Triggers a recoverable media error event
1604
- * @event mediaplayer#recovererror
1605
- */
1606
-
1607
-
1608
- this.trigger('recovererror');
1609
- },
1610
-
1611
1589
  /**
1612
1590
  * Event called when the media is played
1613
1591
  * @private
@@ -1649,11 +1627,13 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1649
1627
 
1650
1628
  this._playingState(false, true);
1651
1629
 
1652
- this._updatePosition(0); // disable GUI when the play limit is reached
1630
+ this._updatePosition(0); // disable when the play limit is reached
1653
1631
 
1654
1632
 
1655
1633
  if (this._playLimitReached()) {
1656
- this._disableGUI();
1634
+ if (!this.is('disabled')) {
1635
+ this.disable();
1636
+ }
1657
1637
  /**
1658
1638
  * Triggers a play limit reached event
1659
1639
  * @event mediaplayer#limitreached
@@ -1694,20 +1674,9 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1694
1674
  * @private
1695
1675
  */
1696
1676
  _onStalled: function _onStalled() {
1697
- var _this9 = this;
1698
-
1699
- this.stalledTimeUpdateCount = 0;
1700
- this.stalledTimer = window.setTimeout(function () {
1701
- var position = _this9.getPosition();
1702
-
1703
- if (position) {
1704
- _this9.positionBeforeStalled = position;
1705
- }
1677
+ this._setState('stalled', true);
1706
1678
 
1707
- _this9._setState('stalled', true);
1708
-
1709
- _this9._setState('ready', false);
1710
- }, this.config.stalledTimeout);
1679
+ this._setState('ready', false);
1711
1680
  },
1712
1681
 
1713
1682
  /**
@@ -1715,15 +1684,6 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1715
1684
  * @private
1716
1685
  */
1717
1686
  _onTimeUpdate: function _onTimeUpdate() {
1718
- if (this.stalledTimer) {
1719
- if (this.stalledTimeUpdateCount === 5) {
1720
- window.clearTimeout(this.stalledTimer);
1721
- this.stalledTimer = null;
1722
- } else {
1723
- this.stalledTimeUpdateCount++;
1724
- }
1725
- }
1726
-
1727
1687
  this._updatePosition(this.player.getPosition());
1728
1688
  /**
1729
1689
  * Triggers a media time update event
@@ -1744,23 +1704,11 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1744
1704
  this.timerId = requestAnimationFrame(this._replayTimeout.bind(this));
1745
1705
 
1746
1706
  if (elapsedSeconds >= parseInt(this.config.replayTimeout, 10)) {
1747
- this._disableGUI();
1748
-
1749
1707
  this.disable();
1750
1708
  cancelAnimationFrame(this.timerId);
1751
1709
  }
1752
1710
  },
1753
1711
 
1754
- /**
1755
- * Disable the player GUI
1756
- * @private
1757
- */
1758
- _disableGUI: function _disableGUI() {
1759
- this._setState('ready', false);
1760
-
1761
- this._setState('canplay', false);
1762
- },
1763
-
1764
1712
  /**
1765
1713
  * Checks if the play limit has been reached
1766
1714
  * @returns {Boolean}
@@ -1875,15 +1823,14 @@ define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/
1875
1823
  * @private
1876
1824
  */
1877
1825
  execute: function execute(command) {
1878
- var ctx = this.player;
1879
- var method = ctx && ctx[command];
1826
+ if (this.player && 'function' === typeof this.player[command]) {
1827
+ var _this$player;
1880
1828
 
1881
- if (_.isFunction(method)) {
1882
1829
  for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1883
1830
  args[_key2 - 1] = arguments[_key2];
1884
1831
  }
1885
1832
 
1886
- return method.apply(ctx, args);
1833
+ return (_this$player = this.player)[command].apply(_this$player, args);
1887
1834
  }
1888
1835
  }
1889
1836
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oat-sa/tao-core-ui",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "displayName": "TAO Core UI",
5
5
  "description": "UI libraries of TAO",
6
6
  "scripts": {