@oat-sa/tao-core-ui 1.58.1 → 1.58.2

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.
Files changed (233) hide show
  1. package/dist/actionbar.js +386 -395
  2. package/dist/adder.js +21 -19
  3. package/dist/animable/absorbable/absorbable.js +204 -213
  4. package/dist/animable/absorbable/css/absorb.css +1 -0
  5. package/dist/animable/absorbable/css/absorb.css.map +1 -1
  6. package/dist/animable/pulsable/pulsable.js +168 -177
  7. package/dist/autocomplete/css/autocomplete.css +1 -0
  8. package/dist/autocomplete/css/autocomplete.css.map +1 -1
  9. package/dist/autocomplete.js +68 -66
  10. package/dist/badge/badge.js +188 -197
  11. package/dist/badge/css/badge.css +1 -0
  12. package/dist/badge/css/badge.css.map +1 -1
  13. package/dist/breadcrumbs.js +275 -284
  14. package/dist/btngrouper.js +5 -5
  15. package/dist/bulkActionPopup.js +490 -495
  16. package/dist/button.js +283 -291
  17. package/dist/cascadingComboBox.js +249 -258
  18. package/dist/ckeditor/ckConfigurator.js +26 -19
  19. package/dist/ckeditor/dtdHandler.js +11 -9
  20. package/dist/class/selector.js +441 -450
  21. package/dist/component/resizable.js +1 -1
  22. package/dist/component/windowed.js +285 -294
  23. package/dist/component.js +419 -428
  24. package/dist/contextualPopup.js +417 -426
  25. package/dist/dashboard.js +300 -309
  26. package/dist/datalist.js +753 -762
  27. package/dist/datatable/filterStrategy/multiple.js +1 -1
  28. package/dist/datatable/filterStrategy/single.js +1 -1
  29. package/dist/datatable.js +1527 -1550
  30. package/dist/dateRange/dateRange.js +393 -402
  31. package/dist/datetime/picker.js +665 -672
  32. package/dist/deleter.js +368 -377
  33. package/dist/destination/selector.js +286 -295
  34. package/dist/dialog/alert.js +3 -3
  35. package/dist/dialog/confirm.js +1 -1
  36. package/dist/dialog/confirmDelete.js +216 -225
  37. package/dist/dialog.js +650 -654
  38. package/dist/disabler.js +8 -8
  39. package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
  40. package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
  41. package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
  42. package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
  43. package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
  44. package/dist/documentViewer/providers/pdfViewer.js +184 -193
  45. package/dist/documentViewer.js +292 -301
  46. package/dist/dropdown.js +383 -392
  47. package/dist/durationer.js +5 -5
  48. package/dist/dynamicComponent.js +597 -598
  49. package/dist/feedback.js +356 -362
  50. package/dist/figure/FigureStateActive.js +117 -108
  51. package/dist/filesender.js +2 -2
  52. package/dist/filter.js +230 -239
  53. package/dist/form/dropdownForm.js +355 -357
  54. package/dist/form/form.js +919 -690
  55. package/dist/form/simpleForm.js +1 -1
  56. package/dist/form/validator/renderer.js +233 -235
  57. package/dist/form/validator/validator.js +257 -189
  58. package/dist/form/widget/definitions.js +1 -1
  59. package/dist/form/widget/providers/checkBox.js +254 -259
  60. package/dist/form/widget/providers/comboBox.js +187 -192
  61. package/dist/form/widget/providers/default.js +8 -9
  62. package/dist/form/widget/providers/hidden.js +170 -179
  63. package/dist/form/widget/providers/hiddenBox.js +262 -267
  64. package/dist/form/widget/providers/radioBox.js +216 -225
  65. package/dist/form/widget/providers/textArea.js +187 -196
  66. package/dist/form/widget/providers/textBox.js +2 -3
  67. package/dist/form/widget/widget.js +473 -475
  68. package/dist/formValidator/formValidator.js +1 -1
  69. package/dist/formValidator/highlighters/message.js +1 -1
  70. package/dist/generis/form/form.js +314 -323
  71. package/dist/generis/validator/validator.js +209 -218
  72. package/dist/generis/widget/checkBox/checkBox.js +218 -227
  73. package/dist/generis/widget/comboBox/comboBox.js +179 -188
  74. package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
  75. package/dist/generis/widget/textBox/textBox.js +169 -178
  76. package/dist/generis/widget/widget.js +246 -255
  77. package/dist/groupedComboBox.js +222 -231
  78. package/dist/groupvalidator.js +2 -2
  79. package/dist/highlighter.js +967 -958
  80. package/dist/image/ImgStateActive/helper.js +7 -5
  81. package/dist/image/ImgStateActive/initHelper.js +49 -43
  82. package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
  83. package/dist/image/ImgStateActive/mediaSizer.js +14 -12
  84. package/dist/image/ImgStateActive.js +72 -70
  85. package/dist/incrementer.js +6 -6
  86. package/dist/inplacer.js +6 -6
  87. package/dist/itemButtonList/css/item-button-list.css +1 -0
  88. package/dist/itemButtonList/css/item-button-list.css.map +1 -1
  89. package/dist/itemButtonList.js +439 -435
  90. package/dist/keyNavigation/navigableDomElement.js +51 -38
  91. package/dist/keyNavigation/navigator.js +85 -70
  92. package/dist/listbox.js +460 -469
  93. package/dist/liststyler.js +8 -8
  94. package/dist/loadingButton/loadingButton.js +209 -218
  95. package/dist/lock.js +476 -485
  96. package/dist/login/login.js +475 -484
  97. package/dist/maths/calculator/basicCalculator.js +235 -244
  98. package/dist/maths/calculator/calculatorComponent.js +3 -3
  99. package/dist/maths/calculator/core/board.js +772 -781
  100. package/dist/maths/calculator/core/expression.js +476 -485
  101. package/dist/maths/calculator/core/labels.js +228 -237
  102. package/dist/maths/calculator/core/tokenizer.js +1 -1
  103. package/dist/maths/calculator/core/tokens.js +163 -170
  104. package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
  105. package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
  106. package/dist/maths/calculator/scientificCalculator.js +327 -336
  107. package/dist/mediaEditor/mediaEditorComponent.js +238 -245
  108. package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
  109. package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
  110. package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
  111. package/dist/mediaplayer/players/html5.js +666 -675
  112. package/dist/mediaplayer/players/youtube.js +419 -424
  113. package/dist/mediaplayer/support.js +11 -10
  114. package/dist/mediaplayer/utils/reminder.js +14 -13
  115. package/dist/mediaplayer/utils/timeObserver.js +10 -11
  116. package/dist/mediaplayer/youtubeManager.js +164 -145
  117. package/dist/mediaplayer.js +1565 -1520
  118. package/dist/mediasizer.js +669 -678
  119. package/dist/modal.js +10 -17
  120. package/dist/pageSizeSelector.js +219 -228
  121. package/dist/pagination/providers/pages.js +280 -289
  122. package/dist/pagination/providers/simple.js +192 -201
  123. package/dist/previewer.js +30 -30
  124. package/dist/progressbar.js +4 -4
  125. package/dist/report.js +347 -356
  126. package/dist/resource/filters.js +271 -280
  127. package/dist/resource/list.js +1264 -1273
  128. package/dist/resource/selector.js +865 -874
  129. package/dist/resource/tree.js +1483 -1492
  130. package/dist/resourcemgr/fileBrowser.js +564 -569
  131. package/dist/resourcemgr/filePreview.js +16 -16
  132. package/dist/resourcemgr/fileSelector.js +515 -524
  133. package/dist/resourcemgr/util/updatePermissions.js +2 -2
  134. package/dist/resourcemgr.js +306 -315
  135. package/dist/searchModal/advancedSearch.js +796 -767
  136. package/dist/searchModal.js +114 -91
  137. package/dist/switch/switch.js +298 -307
  138. package/dist/tabs.js +598 -575
  139. package/dist/taskQueue/status.js +312 -321
  140. package/dist/taskQueue/table.js +375 -384
  141. package/dist/taskQueue/taskQueueModel.js +488 -472
  142. package/dist/taskQueueButton/taskable.js +264 -273
  143. package/dist/taskQueueButton/treeButton.js +189 -198
  144. package/dist/themeLoader.js +24 -23
  145. package/dist/themes.js +1 -1
  146. package/dist/toggler.js +3 -3
  147. package/dist/tooltip.js +295 -304
  148. package/dist/transformer.js +2 -2
  149. package/dist/tristateCheckboxGroup.js +311 -320
  150. package/dist/uploader.js +687 -696
  151. package/dist/validator/Report.js +1 -1
  152. package/dist/validator/Validator.js +3 -3
  153. package/dist/validator/validators.js +9 -9
  154. package/dist/validator.js +240 -230
  155. package/dist/waitForMedia.js +1 -1
  156. package/package.json +3 -3
  157. package/src/animable/absorbable/css/absorb.css +1 -0
  158. package/src/animable/absorbable/css/absorb.css.map +1 -1
  159. package/src/autocomplete/css/autocomplete.css +1 -0
  160. package/src/autocomplete/css/autocomplete.css.map +1 -1
  161. package/src/badge/css/badge.css +1 -0
  162. package/src/badge/css/badge.css.map +1 -1
  163. package/src/ckeditor/ckConfigurator.js +4 -0
  164. package/src/itemButtonList/css/item-button-list.css +1 -0
  165. package/src/itemButtonList/css/item-button-list.css.map +1 -1
  166. package/src/.DS_Store +0 -0
  167. package/src/css/basic.css +0 -7826
  168. package/src/css/basic.css.map +0 -1
  169. package/src/css/ckeditor/skins/tao/css/dialog.css +0 -950
  170. package/src/css/ckeditor/skins/tao/css/dialog.css.map +0 -1
  171. package/src/css/ckeditor/skins/tao/css/editor.css +0 -1850
  172. package/src/css/ckeditor/skins/tao/css/editor.css.map +0 -1
  173. package/src/scss/.DS_Store +0 -0
  174. package/src/scss/basic.scss +0 -16
  175. package/src/scss/ckeditor/skins/tao/scss/dialog.scss +0 -763
  176. package/src/scss/ckeditor/skins/tao/scss/editor.scss +0 -111
  177. package/src/scss/ckeditor/skins/tao/scss/inc/_ck-icons.scss +0 -59
  178. package/src/scss/ckeditor/skins/tao/scss/inc/_colorpanel.scss +0 -118
  179. package/src/scss/ckeditor/skins/tao/scss/inc/_elementspath.scss +0 -69
  180. package/src/scss/ckeditor/skins/tao/scss/inc/_mainui.scss +0 -194
  181. package/src/scss/ckeditor/skins/tao/scss/inc/_menu.scss +0 -181
  182. package/src/scss/ckeditor/skins/tao/scss/inc/_panel.scss +0 -200
  183. package/src/scss/ckeditor/skins/tao/scss/inc/_presets.scss +0 -32
  184. package/src/scss/ckeditor/skins/tao/scss/inc/_reset.scss +0 -101
  185. package/src/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -213
  186. package/src/scss/ckeditor/skins/tao/scss/inc/_tao.scss +0 -59
  187. package/src/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +0 -301
  188. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
  189. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot.b64 +0 -1
  190. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
  191. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff.b64 +0 -1
  192. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
  193. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot.b64 +0 -1
  194. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
  195. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff.b64 +0 -1
  196. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot +0 -0
  197. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot.b64 +0 -1
  198. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff +0 -0
  199. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff.b64 +0 -1
  200. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
  201. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot.b64 +0 -1
  202. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
  203. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff.b64 +0 -1
  204. package/src/scss/font/tao/tao.eot +0 -0
  205. package/src/scss/font/tao/tao.svg +0 -235
  206. package/src/scss/font/tao/tao.ttf +0 -0
  207. package/src/scss/font/tao/tao.woff +0 -0
  208. package/src/scss/inc/_base.scss +0 -496
  209. package/src/scss/inc/_bootstrap.scss +0 -6
  210. package/src/scss/inc/_buttons.scss +0 -114
  211. package/src/scss/inc/_colors.scss +0 -88
  212. package/src/scss/inc/_feedback.scss +0 -150
  213. package/src/scss/inc/_flex-grid.scss +0 -15
  214. package/src/scss/inc/_fonts.scss +0 -4
  215. package/src/scss/inc/_forms.scss +0 -827
  216. package/src/scss/inc/_functions.scss +0 -283
  217. package/src/scss/inc/_grid.scss +0 -66
  218. package/src/scss/inc/_jquery.nouislider.scss +0 -254
  219. package/src/scss/inc/_normalize.scss +0 -528
  220. package/src/scss/inc/_report.scss +0 -68
  221. package/src/scss/inc/_secondary-properties.scss +0 -89
  222. package/src/scss/inc/_select2.scss +0 -634
  223. package/src/scss/inc/_toolbars.scss +0 -155
  224. package/src/scss/inc/_tooltip.scss +0 -312
  225. package/src/scss/inc/_variables.scss +0 -21
  226. package/src/scss/inc/base/_highlight.scss +0 -5
  227. package/src/scss/inc/base/_list-style.scss +0 -59
  228. package/src/scss/inc/base/_svg.scss +0 -3
  229. package/src/scss/inc/base/_table.scss +0 -63
  230. package/src/scss/inc/fonts/_source-sans-pro.scss +0 -29
  231. package/src/scss/inc/fonts/_tao-icon-classes.scss +0 -226
  232. package/src/scss/inc/fonts/_tao-icon-def.scss +0 -12
  233. package/src/scss/inc/fonts/_tao-icon-vars.scss +0 -240
@@ -1,1831 +1,1876 @@
1
1
  define(['jquery', 'lodash', 'async', 'util/urlParser', 'core/eventifier', 'core/mimetype', 'core/store', 'ui/mediaplayer/support', 'ui/mediaplayer/players', 'handlebars', 'i18n', 'lib/dompurify/purify', 'css!ui/mediaplayer/css/player.css', 'nouislider'], function ($$1, _, async, UrlParser, eventifier, mimetype, store, support, players, Handlebars, __, DOMPurify, player_css, nouislider) { 'use strict';
2
2
 
3
- $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
4
- _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
5
- async = async && Object.prototype.hasOwnProperty.call(async, 'default') ? async['default'] : async;
6
- UrlParser = UrlParser && Object.prototype.hasOwnProperty.call(UrlParser, 'default') ? UrlParser['default'] : UrlParser;
7
- eventifier = eventifier && Object.prototype.hasOwnProperty.call(eventifier, 'default') ? eventifier['default'] : eventifier;
8
- mimetype = mimetype && Object.prototype.hasOwnProperty.call(mimetype, 'default') ? mimetype['default'] : mimetype;
9
- store = store && Object.prototype.hasOwnProperty.call(store, 'default') ? store['default'] : store;
10
- support = support && Object.prototype.hasOwnProperty.call(support, 'default') ? support['default'] : support;
11
- players = players && Object.prototype.hasOwnProperty.call(players, 'default') ? players['default'] : players;
12
- Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
13
- __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
14
- DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
15
-
3
+ $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
4
+ _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
5
+ async = async && Object.prototype.hasOwnProperty.call(async, 'default') ? async['default'] : async;
6
+ UrlParser = UrlParser && Object.prototype.hasOwnProperty.call(UrlParser, 'default') ? UrlParser['default'] : UrlParser;
7
+ eventifier = eventifier && Object.prototype.hasOwnProperty.call(eventifier, 'default') ? eventifier['default'] : eventifier;
8
+ mimetype = mimetype && Object.prototype.hasOwnProperty.call(mimetype, 'default') ? mimetype['default'] : mimetype;
9
+ store = store && Object.prototype.hasOwnProperty.call(store, 'default') ? store['default'] : store;
10
+ support = support && Object.prototype.hasOwnProperty.call(support, 'default') ? support['default'] : support;
11
+ players = players && Object.prototype.hasOwnProperty.call(players, 'default') ? players['default'] : players;
12
+ Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
13
+ __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
14
+ DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
15
+
16
+ function _typeof(obj) {
17
+ "@babel/helpers - typeof";
18
+
19
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
20
+ return typeof obj;
21
+ } : function (obj) {
22
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
23
+ }, _typeof(obj);
24
+ }
25
+
26
+ function Helpers0 (hb) {
27
+ //register a i18n helper
28
+ hb.registerHelper('__', function (key) {
29
+ return __(key);
30
+ });
16
31
  /**
17
- * This program is free software; you can redistribute it and/or
18
- * modify it under the terms of the GNU General Public License
19
- * as published by the Free Software Foundation; under version 2
20
- * of the License (non-upgradable).
21
- *
22
- * This program is distributed in the hope that it will be useful,
23
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
- * GNU General Public License for more details.
26
- *
27
- * You should have received a copy of the GNU General Public License
28
- * along with this program; if not, write to the Free Software
29
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30
- *
31
- * Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
32
- *
32
+ * Register dompurify helper
33
33
  *
34
+ * https://github.com/cure53/DOMPurify
35
+ * with config SAFE_FOR_TEMPLATES: true
36
+ * to make output safe for template systems
34
37
  */
35
- function Helpers0 (hb) {
36
- //register a i18n helper
37
- hb.registerHelper('__', function (key) {
38
- return __(key);
39
- });
40
- /**
41
- * Register dompurify helper
42
- *
43
- * https://github.com/cure53/DOMPurify
44
- * with config SAFE_FOR_TEMPLATES: true
45
- * to make output safe for template systems
46
- */
47
38
 
48
- hb.registerHelper('dompurify', function (context) {
49
- return DOMPurify.sanitize(context);
50
- });
51
- /**
52
- * Register join helper
53
- *
54
- * Example :
55
- * var values = {a:v1, b:v2, c:v3};
56
- * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
57
- * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
58
- */
59
-
60
- hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
61
- var fragments = [];
62
- keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
63
- fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
64
- wrapper = typeof wrapper === 'string' ? wrapper : '"';
39
+ hb.registerHelper('dompurify', function (context) {
40
+ return DOMPurify.sanitize(context);
41
+ });
42
+ /**
43
+ * Register join helper
44
+ *
45
+ * Example :
46
+ * var values = {a:v1, b:v2, c:v3};
47
+ * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
48
+ * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
49
+ */
65
50
 
66
- _.forIn(arr, function (value, key) {
67
- var fragment = '';
51
+ hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
52
+ var fragments = [];
53
+ keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
54
+ fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
55
+ wrapper = typeof wrapper === 'string' ? wrapper : '"';
68
56
 
69
- if (value !== null || value !== undefined) {
70
- if (typeof value === 'boolean') {
71
- value = value ? 'true' : 'false';
72
- } else if (typeof value === 'object') {
73
- value = _.values(value).join(' ');
74
- }
75
- } else {
76
- value = '';
77
- }
57
+ _.forIn(arr, function (value, key) {
58
+ var fragment = '';
78
59
 
79
- if (keyValueGlue !== undefined) {
80
- fragment += key + keyValueGlue;
60
+ if (value !== null || value !== undefined) {
61
+ if (typeof value === 'boolean') {
62
+ value = value ? 'true' : 'false';
63
+ } else if (_typeof(value) === 'object') {
64
+ value = _.values(value).join(' ');
81
65
  }
82
-
83
- fragment += wrapper + value + wrapper;
84
- fragments.push(fragment);
85
- });
86
-
87
- return fragments.join(fragmentGlue);
88
- }); //register a classic "for loop" helper
89
- //it also adds a local variable "i" as the index in each iteration loop
90
-
91
- hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
92
- var ret = '';
93
- startIndex = parseInt(startIndex);
94
- stopIndex = parseInt(stopIndex);
95
- increment = parseInt(increment);
96
-
97
- for (var i = startIndex; i < stopIndex; i += increment) {
98
- ret += options.fn(_.extend({}, this, {
99
- i: i
100
- }));
101
- }
102
-
103
- return ret;
104
- });
105
- hb.registerHelper('equal', function (var1, var2, options) {
106
- if (var1 == var2) {
107
- return options.fn(this);
108
66
  } else {
109
- return options.inverse(this);
67
+ value = '';
110
68
  }
111
- }); // register a "get property" helper
112
- // it gets the named property from the provided context
113
69
 
114
- hb.registerHelper('property', function (name, context) {
115
- return context[name] || '';
116
- }); // register an 'includes' helper
117
- // it checks if value is in array
118
-
119
- hb.registerHelper('includes', function (haystack, needle, options) {
120
- if (_.contains(haystack, needle)) {
121
- return options.fn(this);
70
+ if (keyValueGlue !== undefined) {
71
+ fragment += key + keyValueGlue;
122
72
  }
123
- });
124
- }
125
73
 
126
- if (!Helpers0.__initialized) {
127
- Helpers0(Handlebars);
128
- Helpers0.__initialized = true;
129
- }
130
- var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
131
- this.compilerInfo = [4,'>= 1.0.0'];
132
- helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
133
- var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing;
134
-
135
-
136
- buffer += "<div class=\"mediaplayer ";
137
- if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
138
- else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
139
- buffer += escapeExpression(stack1)
140
- + "\">\n <div class=\"player\">\n <div class=\"player-overlay\">\n <a class=\"action play\" data-control=\"play\"><span class=\"icon icon-play\" title=\""
141
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
142
- + "\"></span></a>\n <a class=\"action play\" data-control=\"pause\"><span class=\"icon icon-pause\" title=\""
143
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Pause", options) : helperMissing.call(depth0, "__", "Pause", options)))
144
- + "\"></span></a>\n <a class=\"action reload\" data-control=\"start\">\n <span class=\"icon icon-play\" title=\""
145
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Start", options) : helperMissing.call(depth0, "__", "Start", options)))
146
- + "\"></span>\n <div class=\"message\">"
147
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to start", options) : helperMissing.call(depth0, "__", "Click to start", options)))
148
- + "</div>\n </a>\n <a class=\"action reload\" data-control=\"reload\">\n <div class=\"icon icon-reload\" title=\""
149
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Reload", options) : helperMissing.call(depth0, "__", "Reload", options)))
150
- + "\"></div>\n <div class=\"message\">"
151
- + 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)))
152
- + " "
153
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to reload.", options) : helperMissing.call(depth0, "__", "Click to reload.", options)))
154
- + "</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=\""
155
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
156
- + "\"><span class=\"icon icon-play\"></span></a>\n <a class=\"action play\" data-control=\"pause\" title=\""
157
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Pause", options) : helperMissing.call(depth0, "__", "Pause", options)))
158
- + "\"><span class=\"icon icon-pause\"></span></a>\n </div>\n <div class=\"control seek\"><div class=\"slider\"></div></div>\n <div class=\"control infos timer\">\n <span class=\"info time\" data-control=\"time-cur\" title=\""
159
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Current playback position", options) : helperMissing.call(depth0, "__", "Current playback position", options)))
160
- + "\">--:--</span>\n <span class=\"info time\" data-control=\"time-end\" title=\""
161
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Total duration", options) : helperMissing.call(depth0, "__", "Total duration", options)))
162
- + "\">--:--</span>\n </div>\n <div class=\"control actions sound\">\n <div class=\"volume\"><div class=\"slider\"></div></div>\n <a class=\"action mute\" data-control=\"mute\" title=\""
163
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Mute", options) : helperMissing.call(depth0, "__", "Mute", options)))
164
- + "\"><span class=\"icon icon-sound\"></span></a>\n <a class=\"action mute\" data-control=\"unmute\" title=\""
165
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Restore sound", options) : helperMissing.call(depth0, "__", "Restore sound", options)))
166
- + "\"><span class=\"icon icon-mute\"></span></a>\n </div>\n </div>\n </div>\n <div class=\"error\">\n <div class=\"message\">"
167
- + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "This media cannot be played!", options) : helperMissing.call(depth0, "__", "This media cannot be played!", options)))
168
- + "</div>\n </div>\n</div>\n";
169
- return buffer;
74
+ fragment += wrapper + value + wrapper;
75
+ fragments.push(fragment);
170
76
  });
171
- function playerTpl(data, options, asString) {
172
- var html = Template(data, options);
173
- return (asString || true) ? html : $(html);
174
- }
175
-
176
- /**
177
- * This program is free software; you can redistribute it and/or
178
- * modify it under the terms of the GNU General Public License
179
- * as published by the Free Software Foundation; under version 2
180
- * of the License (non-upgradable).
181
- *
182
- * This program is distributed in the hope that it will be useful,
183
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
184
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
185
- * GNU General Public License for more details.
186
- *
187
- * You should have received a copy of the GNU General Public License
188
- * along with this program; if not, write to the Free Software
189
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
190
- *
191
- * Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
192
- */
193
- /**
194
- * CSS namespace
195
- * @type {String}
196
- */
197
-
198
- const ns = '.mediaplayer';
199
- /**
200
- * Minimum value of the volume
201
- * @type {Number}
202
- */
203
-
204
- const volumeMin = 0;
205
- /**
206
- * Maximum value of the volume
207
- * @type {Number}
208
- */
209
77
 
210
- const volumeMax = 100;
211
- /**
212
- * Threshold (minimum required space above the player) to display the volume
213
- * above the bar.
214
- * @type {Number}
215
- */
78
+ return fragments.join(fragmentGlue);
79
+ }); //register a classic "for loop" helper
80
+ //it also adds a local variable "i" as the index in each iteration loop
216
81
 
217
- const volumePositionThreshold = 200;
218
- /**
219
- * Some default values
220
- * @type {Object}
221
- */
82
+ hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
83
+ var ret = '';
84
+ startIndex = parseInt(startIndex);
85
+ stopIndex = parseInt(stopIndex);
86
+ increment = parseInt(increment);
222
87
 
223
- const defaults = {
224
- type: 'video/mp4',
225
- video: {
226
- width: '100%',
227
- height: 'auto'
228
- },
229
- audio: {
230
- width: '100%',
231
- height: 'auto'
232
- },
233
- youtube: {
234
- width: 640,
235
- height: 360
236
- },
237
- options: {
238
- volume: 80,
239
- startMuted: false,
240
- maxPlays: 0,
241
- replayTimeout: 0,
242
- canPause: true,
243
- canSeek: true,
244
- loop: false,
245
- autoStart: false,
246
- preview: true,
247
- debug: false
88
+ for (var i = startIndex; i < stopIndex; i += increment) {
89
+ ret += options.fn(_.extend({}, this, {
90
+ i: i
91
+ }));
248
92
  }
249
- };
250
- /**
251
- * Ensures a value is a number
252
- * @param {Number|String} value
253
- * @returns {Number}
254
- */
255
-
256
- const ensureNumber = value => {
257
- const floatValue = parseFloat(value);
258
- return isFinite(floatValue) ? floatValue : 0;
259
- };
260
- /**
261
- * Format a number to string with leading zeros
262
- * @param {Number} n
263
- * @param {Number} len
264
- * @returns {String}
265
- */
266
-
267
93
 
268
- const leadingZero = (n, len) => {
269
- let value = n.toString();
270
-
271
- while (value.length < len) {
272
- value = `0${value}`;
94
+ return ret;
95
+ });
96
+ hb.registerHelper('equal', function (var1, var2, options) {
97
+ if (var1 == var2) {
98
+ return options.fn(this);
99
+ } else {
100
+ return options.inverse(this);
273
101
  }
102
+ }); // register a "get property" helper
103
+ // it gets the named property from the provided context
274
104
 
275
- return value;
276
- };
277
- /**
278
- * Formats a time value to string
279
- * @param {Number} time
280
- * @returns {String}
281
- */
282
-
283
-
284
- const timerFormat = time => {
285
- const seconds = Math.floor(time % 60);
286
- const minutes = Math.floor(time / 60) % 60;
287
- const hours = Math.floor(time / 3600);
288
- const parts = [];
105
+ hb.registerHelper('property', function (name, context) {
106
+ return context[name] || '';
107
+ }); // register an 'includes' helper
108
+ // it checks if value is in array
289
109
 
290
- if (hours) {
291
- parts.push(hours);
110
+ hb.registerHelper('includes', function (haystack, needle, options) {
111
+ if (_.contains(haystack, needle)) {
112
+ return options.fn(this);
292
113
  }
114
+ });
115
+ }
116
+
117
+ if (!Helpers0.__initialized) {
118
+ Helpers0(Handlebars);
119
+ Helpers0.__initialized = true;
120
+ }
121
+ var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
122
+ this.compilerInfo = [4,'>= 1.0.0'];
123
+ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
124
+ var buffer = "", stack1, helper, options, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing;
125
+
126
+
127
+ buffer += "<div class=\"mediaplayer ";
128
+ if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
129
+ else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
130
+ buffer += escapeExpression(stack1)
131
+ + "\">\n <div class=\"player\">\n <div class=\"player-overlay\">\n <a class=\"action play\" data-control=\"play\"><span class=\"icon icon-play\" title=\""
132
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
133
+ + "\"></span></a>\n <a class=\"action play\" data-control=\"pause\"><span class=\"icon icon-pause\" title=\""
134
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Pause", options) : helperMissing.call(depth0, "__", "Pause", options)))
135
+ + "\"></span></a>\n <a class=\"action reload\" data-control=\"start\">\n <span class=\"icon icon-play\" title=\""
136
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Start", options) : helperMissing.call(depth0, "__", "Start", options)))
137
+ + "\"></span>\n <div class=\"message\">"
138
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to start", options) : helperMissing.call(depth0, "__", "Click to start", options)))
139
+ + "</div>\n </a>\n <a class=\"action reload\" data-control=\"reload\">\n <div class=\"icon icon-reload\" title=\""
140
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Reload", options) : helperMissing.call(depth0, "__", "Reload", options)))
141
+ + "\"></div>\n <div class=\"message\">"
142
+ + 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)))
143
+ + " "
144
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Click to reload.", options) : helperMissing.call(depth0, "__", "Click to reload.", options)))
145
+ + "</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=\""
146
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Play", options) : helperMissing.call(depth0, "__", "Play", options)))
147
+ + "\"><span class=\"icon icon-play\"></span></a>\n <a class=\"action play\" data-control=\"pause\" title=\""
148
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Pause", options) : helperMissing.call(depth0, "__", "Pause", options)))
149
+ + "\"><span class=\"icon icon-pause\"></span></a>\n </div>\n <div class=\"control seek\"><div class=\"slider\"></div></div>\n <div class=\"control infos timer\">\n <span class=\"info time\" data-control=\"time-cur\" title=\""
150
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Current playback position", options) : helperMissing.call(depth0, "__", "Current playback position", options)))
151
+ + "\">--:--</span>\n <span class=\"info time\" data-control=\"time-end\" title=\""
152
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Total duration", options) : helperMissing.call(depth0, "__", "Total duration", options)))
153
+ + "\">--:--</span>\n </div>\n <div class=\"control actions sound\">\n <div class=\"volume\"><div class=\"slider\"></div></div>\n <a class=\"action mute\" data-control=\"mute\" title=\""
154
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Mute", options) : helperMissing.call(depth0, "__", "Mute", options)))
155
+ + "\"><span class=\"icon icon-sound\"></span></a>\n <a class=\"action mute\" data-control=\"unmute\" title=\""
156
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Restore sound", options) : helperMissing.call(depth0, "__", "Restore sound", options)))
157
+ + "\"><span class=\"icon icon-mute\"></span></a>\n </div>\n </div>\n </div>\n <div class=\"error\">\n <div class=\"message\">"
158
+ + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "This media cannot be played!", options) : helperMissing.call(depth0, "__", "This media cannot be played!", options)))
159
+ + "</div>\n </div>\n</div>\n";
160
+ return buffer;
161
+ });
162
+ function playerTpl(data, options, asString) {
163
+ var html = Template(data, options);
164
+ return (asString || true) ? html : $(html);
165
+ }
166
+
167
+ /**
168
+ * This program is free software; you can redistribute it and/or
169
+ * modify it under the terms of the GNU General Public License
170
+ * as published by the Free Software Foundation; under version 2
171
+ * of the License (non-upgradable).
172
+ *
173
+ * This program is distributed in the hope that it will be useful,
174
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
175
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
176
+ * GNU General Public License for more details.
177
+ *
178
+ * You should have received a copy of the GNU General Public License
179
+ * along with this program; if not, write to the Free Software
180
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
181
+ *
182
+ * Copyright (c) 2015-2021 (original work) Open Assessment Technologies SA ;
183
+ */
184
+ /**
185
+ * CSS namespace
186
+ * @type {String}
187
+ */
188
+
189
+ var ns = '.mediaplayer';
190
+ /**
191
+ * Minimum value of the volume
192
+ * @type {Number}
193
+ */
194
+
195
+ var volumeMin = 0;
196
+ /**
197
+ * Maximum value of the volume
198
+ * @type {Number}
199
+ */
200
+
201
+ var volumeMax = 100;
202
+ /**
203
+ * Threshold (minimum required space above the player) to display the volume
204
+ * above the bar.
205
+ * @type {Number}
206
+ */
207
+
208
+ var volumePositionThreshold = 200;
209
+ /**
210
+ * Some default values
211
+ * @type {Object}
212
+ */
213
+
214
+ var defaults = {
215
+ type: 'video/mp4',
216
+ video: {
217
+ width: '100%',
218
+ height: 'auto'
219
+ },
220
+ audio: {
221
+ width: '100%',
222
+ height: 'auto'
223
+ },
224
+ youtube: {
225
+ width: 640,
226
+ height: 360
227
+ },
228
+ options: {
229
+ volume: 80,
230
+ startMuted: false,
231
+ maxPlays: 0,
232
+ replayTimeout: 0,
233
+ canPause: true,
234
+ canSeek: true,
235
+ loop: false,
236
+ autoStart: false,
237
+ preview: true,
238
+ debug: false
239
+ }
240
+ };
241
+ /**
242
+ * Ensures a value is a number
243
+ * @param {Number|String} value
244
+ * @returns {Number}
245
+ */
246
+
247
+ var ensureNumber = function ensureNumber(value) {
248
+ var floatValue = parseFloat(value);
249
+ return isFinite(floatValue) ? floatValue : 0;
250
+ };
251
+ /**
252
+ * Format a number to string with leading zeros
253
+ * @param {Number} n
254
+ * @param {Number} len
255
+ * @returns {String}
256
+ */
257
+
258
+
259
+ var leadingZero = function leadingZero(n, len) {
260
+ var value = n.toString();
261
+
262
+ while (value.length < len) {
263
+ value = "0".concat(value);
264
+ }
293
265
 
294
- parts.push(leadingZero(minutes, 2));
295
- parts.push(leadingZero(seconds, 2));
296
- return parts.join(':');
297
- };
298
- /**
299
- * Checks if a type needs to be adjusted
300
- * @param {String} type
301
- * @returns {Boolean}
302
- */
303
-
304
-
305
- const needTypeAdjust = type => {
306
- return 'string' === typeof type && type.indexOf('application') === 0;
307
- };
308
- /**
309
- * Adjust bad type by apllying heuristic on URI
310
- * @param {Object|String} source
311
- * @returns {String}
312
- */
266
+ return value;
267
+ };
268
+ /**
269
+ * Formats a time value to string
270
+ * @param {Number} time
271
+ * @returns {String}
272
+ */
313
273
 
314
274
 
315
- const getAdjustedType = source => {
316
- let type = 'video/ogg';
317
- const url = source && source.src || source;
318
- const ext = url && url.substr(-4);
275
+ var timerFormat = function timerFormat(time) {
276
+ var seconds = Math.floor(time % 60);
277
+ var minutes = Math.floor(time / 60) % 60;
278
+ var hours = Math.floor(time / 3600);
279
+ var parts = [];
319
280
 
320
- if (ext === '.ogg' || ext === '.oga') {
321
- type = 'audio/ogg';
322
- }
281
+ if (hours) {
282
+ parts.push(hours);
283
+ }
323
284
 
324
- return type;
325
- };
326
- /**
327
- * Extract a list of media sources from a config object
328
- * @param {Object} config
329
- * @returns {Array}
330
- */
285
+ parts.push(leadingZero(minutes, 2));
286
+ parts.push(leadingZero(seconds, 2));
287
+ return parts.join(':');
288
+ };
289
+ /**
290
+ * Checks if a type needs to be adjusted
291
+ * @param {String} type
292
+ * @returns {Boolean}
293
+ */
294
+
295
+
296
+ var needTypeAdjust = function needTypeAdjust(type) {
297
+ return 'string' === typeof type && type.indexOf('application') === 0;
298
+ };
299
+ /**
300
+ * Adjust bad type by apllying heuristic on URI
301
+ * @param {Object|String} source
302
+ * @returns {String}
303
+ */
304
+
305
+
306
+ var getAdjustedType = function getAdjustedType(source) {
307
+ var type = 'video/ogg';
308
+ var url = source && source.src || source;
309
+ var ext = url && url.substr(-4);
310
+
311
+ if (ext === '.ogg' || ext === '.oga') {
312
+ type = 'audio/ogg';
313
+ }
331
314
 
315
+ return type;
316
+ };
317
+ /**
318
+ * Extract a list of media sources from a config object
319
+ * @param {Object} config
320
+ * @returns {Array}
321
+ */
332
322
 
333
- const configToSources = config => {
334
- let sources = config.sources || [];
335
- let url = config.url;
336
323
 
337
- if (!_.isArray(sources)) {
338
- sources = [sources];
339
- }
324
+ var configToSources = function configToSources(config) {
325
+ var sources = config.sources || [];
326
+ var url = config.url;
340
327
 
341
- if (url) {
342
- if (!_.isArray(config.url)) {
343
- url = [url];
344
- }
328
+ if (!_.isArray(sources)) {
329
+ sources = [sources];
330
+ }
345
331
 
346
- sources = sources.concat(url);
332
+ if (url) {
333
+ if (!_.isArray(config.url)) {
334
+ url = [url];
347
335
  }
348
336
 
349
- return sources;
350
- };
351
- /**
352
- * Checks if the browser can play media
353
- * @param {String} sizeProps Width or Height
354
- * @returns {Boolean}
355
- */
356
-
337
+ sources = sources.concat(url);
338
+ }
357
339
 
358
- const isResponsiveSize = sizeProps => {
359
- return /%/.test(sizeProps) || sizeProps === 'auto';
360
- };
340
+ return sources;
341
+ };
342
+ /**
343
+ * Checks if the browser can play media
344
+ * @param {String} sizeProps Width or Height
345
+ * @returns {Boolean}
346
+ */
347
+
348
+
349
+ var isResponsiveSize = function isResponsiveSize(sizeProps) {
350
+ return /%/.test(sizeProps) || sizeProps === 'auto';
351
+ };
352
+ /**
353
+ * Builds a media player instance
354
+ * @param {Object} config
355
+ * @param {String} config.type - The type of media to play, say `audio`, `video`, or `youtube`. The default is `video`.
356
+ * It might also contain the MIME type of the media as a shorthand.
357
+ * @param {String|Array} [config.url] - The URL to the media. If several media are proposed as alternatives,
358
+ * please look at the `sources` option instead.
359
+ * @param {String} [config.mimeType] - The MIME type of the media. If omitted, the player will try to extract it
360
+ * from the `type` property, otherwise it will request the server to get the content-type.
361
+ * @param {Array} [config.sources] - A list of URL if several media can be proposed. Each entry may be either a
362
+ * string (single URL), or an object containing both the URL and the MIME type ({src: string, type: string}).
363
+ * @param {String|jQuery|HTMLElement} [config.renderTo] - An optional container in which renders the player
364
+ * @param {Boolean} [config.canSeek] - The player allows to reach an arbitrary position within the media using the duration bar
365
+ * @param {Boolean} [config.loop] - The media will be played continuously
366
+ * @param {Boolean} [config.canPause] - The player can be paused
367
+ * @param {Boolean} [config.startMuted] - The player should be initially muted
368
+ * @param {Boolean} [config.autoStart] - The player starts as soon as it is displayed
369
+ * @param {Number} [config.autoStartAt] - The time position at which the player should start
370
+ * @param {Number} [config.maxPlays] - Sets a few number of plays (default: infinite)
371
+ * @param {Number} [config.replayTimeout] - disable the possibility to replay a media after this timeout, in seconds (default: 0)
372
+ * @param {Number} [config.volume] - Sets the sound volume (default: 80)
373
+ * @param {Number} [config.width] - Sets the width of the player (default: depends on media type)
374
+ * @param {Number} [config.height] - Sets the height of the player (default: depends on media type)
375
+ * @param {Boolean} [config.preview] - Enables the media preview (load media metadata)
376
+ * @param {Boolean} [config.debug] - Enables the debug mode
377
+ * @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
378
+ * @event render - Event triggered when the player is rendering
379
+ * @event error - Event triggered when the player throws an unrecoverable error
380
+ * @event ready - Event triggered when the player is fully ready
381
+ * @event play - Event triggered when the playback is starting
382
+ * @event update - Event triggered while the player is playing
383
+ * @event pause - Event triggered when the playback is paused
384
+ * @event ended - Event triggered when the playback is ended
385
+ * @event limitreached - Event triggered when the play limit has been reached
386
+ * @event destroy - Event triggered when the player is destroying
387
+ * @returns {mediaplayer}
388
+ */
389
+
390
+
391
+ function mediaplayerFactory(config) {
361
392
  /**
362
- * Builds a media player instance
363
- * @param {Object} config
364
- * @param {String} config.type - The type of media to play, say `audio`, `video`, or `youtube`. The default is `video`.
365
- * It might also contain the MIME type of the media as a shorthand.
366
- * @param {String|Array} [config.url] - The URL to the media. If several media are proposed as alternatives,
367
- * please look at the `sources` option instead.
368
- * @param {String} [config.mimeType] - The MIME type of the media. If omitted, the player will try to extract it
369
- * from the `type` property, otherwise it will request the server to get the content-type.
370
- * @param {Array} [config.sources] - A list of URL if several media can be proposed. Each entry may be either a
371
- * string (single URL), or an object containing both the URL and the MIME type ({src: string, type: string}).
372
- * @param {String|jQuery|HTMLElement} [config.renderTo] - An optional container in which renders the player
373
- * @param {Boolean} [config.canSeek] - The player allows to reach an arbitrary position within the media using the duration bar
374
- * @param {Boolean} [config.loop] - The media will be played continuously
375
- * @param {Boolean} [config.canPause] - The player can be paused
376
- * @param {Boolean} [config.startMuted] - The player should be initially muted
377
- * @param {Boolean} [config.autoStart] - The player starts as soon as it is displayed
378
- * @param {Number} [config.autoStartAt] - The time position at which the player should start
379
- * @param {Number} [config.maxPlays] - Sets a few number of plays (default: infinite)
380
- * @param {Number} [config.replayTimeout] - disable the possibility to replay a media after this timeout, in seconds (default: 0)
381
- * @param {Number} [config.volume] - Sets the sound volume (default: 80)
382
- * @param {Number} [config.width] - Sets the width of the player (default: depends on media type)
383
- * @param {Number} [config.height] - Sets the height of the player (default: depends on media type)
384
- * @param {Boolean} [config.preview] - Enables the media preview (load media metadata)
385
- * @param {Boolean} [config.debug] - Enables the debug mode
386
- * @param {number} [config.config.stalledDetectionDelay] - The delay before considering a media is stalled
387
- * @event render - Event triggered when the player is rendering
388
- * @event error - Event triggered when the player throws an unrecoverable error
389
- * @event ready - Event triggered when the player is fully ready
390
- * @event play - Event triggered when the playback is starting
391
- * @event update - Event triggered while the player is playing
392
- * @event pause - Event triggered when the playback is paused
393
- * @event ended - Event triggered when the playback is ended
394
- * @event limitreached - Event triggered when the play limit has been reached
395
- * @event destroy - Event triggered when the player is destroying
396
- * @returns {mediaplayer}
393
+ * Defines a media player object
394
+ * @type {Object}
397
395
  */
398
-
399
-
400
- function mediaplayerFactory(config) {
396
+ var mediaplayer = {
401
397
  /**
402
- * Defines a media player object
403
- * @type {Object}
398
+ * Initializes the media player
399
+ * @param {Object} config
400
+ * @returns {mediaplayer}
404
401
  */
405
- const mediaplayer = {
406
- /**
407
- * Initializes the media player
408
- * @param {Object} config
409
- * @returns {mediaplayer}
410
- */
411
- init(config) {
412
- // load the config set, discard null values in order to allow defaults to be set
413
- this.config = _.omit(config || {}, value => typeof value === 'undefined' || value === null);
414
-
415
- _.defaults(this.config, defaults.options);
416
-
417
- if (!this.config.mimeType && 'string' === typeof this.config.type && this.config.type.indexOf('/') > 0) {
418
- this.config.mimeType = this.config.type;
419
- }
402
+ init: function init(config) {
403
+ var _this = this;
420
404
 
421
- this._setType(this.config.type || defaults.type);
405
+ // load the config set, discard null values in order to allow defaults to be set
406
+ this.config = _.omit(config || {}, function (value) {
407
+ return typeof value === 'undefined' || value === null;
408
+ });
422
409
 
423
- this._reset();
410
+ _.defaults(this.config, defaults.options);
424
411
 
425
- this._updateVolumeFromStore();
412
+ if (!this.config.mimeType && 'string' === typeof this.config.type && this.config.type.indexOf('/') > 0) {
413
+ this.config.mimeType = this.config.type;
414
+ }
426
415
 
427
- this._initEvents();
416
+ this._setType(this.config.type || defaults.type);
428
417
 
429
- this._initSources(() => {
430
- if (!this.is('youtube')) {
431
- _.forEach(this.config.sources, source => {
432
- if (source && source.type && source.type.indexOf('audio') === 0) {
433
- this._setType(source.type);
418
+ this._reset();
434
419
 
435
- this._initType();
420
+ this._updateVolumeFromStore();
436
421
 
437
- return false;
438
- }
439
- });
440
- }
422
+ this._initEvents();
441
423
 
442
- if (this.config.renderTo) {
443
- _.defer(() => this.render());
444
- }
445
- });
424
+ this._initSources(function () {
425
+ if (!_this.is('youtube')) {
426
+ _.forEach(_this.config.sources, function (source) {
427
+ if (source && source.type && source.type.indexOf('audio') === 0) {
428
+ _this._setType(source.type);
446
429
 
447
- return this;
448
- },
430
+ _this._initType();
449
431
 
450
- /**
451
- * Uninstalls the media player
452
- * @returns {mediaplayer}
453
- */
454
- destroy() {
455
- /**
456
- * Triggers a destroy event
457
- * @event mediaplayer#destroy
458
- */
459
- this.trigger('destroy');
432
+ return false;
433
+ }
434
+ });
435
+ }
460
436
 
461
- if (this.player) {
462
- this.player.destroy();
437
+ if (_this.config.renderTo) {
438
+ _.defer(function () {
439
+ return _this.render();
440
+ });
463
441
  }
442
+ });
464
443
 
465
- if (this.$component) {
466
- this._unbindEvents();
444
+ return this;
445
+ },
467
446
 
468
- this._destroySlider(this.$seekSlider);
447
+ /**
448
+ * Uninstalls the media player
449
+ * @returns {mediaplayer}
450
+ */
451
+ destroy: function destroy() {
452
+ /**
453
+ * Triggers a destroy event
454
+ * @event mediaplayer#destroy
455
+ */
456
+ this.trigger('destroy');
469
457
 
470
- this._destroySlider(this.$volumeSlider);
458
+ if (this.player) {
459
+ this.player.destroy();
460
+ }
471
461
 
472
- this.$component.remove();
473
- }
462
+ if (this.$component) {
463
+ this._unbindEvents();
474
464
 
475
- this._reset();
465
+ this._destroySlider(this.$seekSlider);
476
466
 
477
- return this;
478
- },
467
+ this._destroySlider(this.$volumeSlider);
479
468
 
480
- /**
481
- * Renders the media player according to the media type
482
- * @param {String|jQuery|HTMLElement} [to]
483
- * @returns {mediaplayer}
484
- */
485
- render(to) {
486
- const renderTo = to || this.config.renderTo || this.$container;
469
+ this.$component.remove();
470
+ }
487
471
 
488
- if (this.$component) {
489
- this.destroy();
490
- }
472
+ this._reset();
491
473
 
492
- this._initState();
474
+ return this;
475
+ },
493
476
 
494
- this._buildDom();
477
+ /**
478
+ * Renders the media player according to the media type
479
+ * @param {String|jQuery|HTMLElement} [to]
480
+ * @returns {mediaplayer}
481
+ */
482
+ render: function render(to) {
483
+ var renderTo = to || this.config.renderTo || this.$container;
495
484
 
496
- if (this.config.preview) {
497
- this._updateDuration(0);
485
+ if (this.$component) {
486
+ this.destroy();
487
+ }
498
488
 
499
- this._updatePosition(0);
500
- }
489
+ this._initState();
501
490
 
502
- this._bindEvents();
491
+ this._buildDom();
503
492
 
504
- this._playingState(false, true);
493
+ if (this.config.preview) {
494
+ this._updateDuration(0);
505
495
 
506
- this._initPlayer();
496
+ this._updatePosition(0);
497
+ }
507
498
 
508
- this._initSize(); // Resize for old items with defined height to avoid big jump
499
+ this._bindEvents();
509
500
 
501
+ this._playingState(false, true);
510
502
 
511
- if (this.config.height && this.config.height !== 'auto') {
512
- this.resize('100%', 'auto');
513
- } else {
514
- this.resize(this.config.width, this.config.height);
515
- }
503
+ this._initPlayer();
516
504
 
517
- this.config.is.rendered = true;
505
+ this._initSize(); // Resize for old items with defined height to avoid big jump
518
506
 
519
- if (renderTo) {
520
- this.$container = $$1(renderTo).append(this.$component);
521
- } // add class if it is stalled
522
507
 
508
+ if (this.config.height && this.config.height !== 'auto') {
509
+ this.resize('100%', 'auto');
510
+ } else {
511
+ this.resize(this.config.width, this.config.height);
512
+ }
523
513
 
524
- if (this.is('stalled')) {
525
- this._setState('stalled', true);
526
- }
527
- /**
528
- * Triggers a render event
529
- * @event mediaplayer#render
530
- * @param {jQuery} $component
531
- */
514
+ this.config.is.rendered = true;
532
515
 
516
+ if (renderTo) {
517
+ this.$container = $$1(renderTo).append(this.$component);
518
+ } // add class if it is stalled
533
519
 
534
- this.trigger('render', this.$component);
535
- return this;
536
- },
537
520
 
521
+ if (this.is('stalled')) {
522
+ this._setState('stalled', true);
523
+ }
538
524
  /**
539
- * Reloads media player after it was stalled
525
+ * Triggers a render event
526
+ * @event mediaplayer#render
527
+ * @param {jQuery} $component
540
528
  */
541
- reload() {
542
- /**
543
- * Triggers a reload event
544
- * @event mediaplayer#reload
545
- */
546
- this.trigger('reload');
547
-
548
- if (this.player) {
549
- this.player.recover();
550
- }
551
529
 
552
- this._setState('stalled', false);
553
530
 
554
- this.setInitialStates();
555
- },
531
+ this.trigger('render', this.$component);
532
+ return this;
533
+ },
556
534
 
535
+ /**
536
+ * Reloads media player after it was stalled
537
+ */
538
+ reload: function reload() {
557
539
  /**
558
- * Set initial states
540
+ * Triggers a reload event
541
+ * @event mediaplayer#reload
559
542
  */
560
- setInitialStates() {
561
- if (!this.is('stalled')) {
562
- this._setState('ready', true);
563
- }
543
+ this.trigger('reload');
564
544
 
565
- this._setState('canplay', true);
545
+ if (this.player) {
546
+ this.player.recover();
547
+ }
566
548
 
567
- this._setState('canpause', this.config.canPause);
549
+ this._setState('stalled', false);
568
550
 
569
- this._setState('canseek', this.config.canSeek);
551
+ this.setInitialStates();
552
+ },
570
553
 
571
- this._setState('loading', false);
572
- },
554
+ /**
555
+ * Set initial states
556
+ */
557
+ setInitialStates: function setInitialStates() {
558
+ if (!this.is('stalled')) {
559
+ this._setState('ready', true);
560
+ }
573
561
 
574
- /**
575
- * Sets the start position inside the media
576
- * @param {Number} time - The start position in seconds
577
- * @param {*} [internal] - Internal use
578
- * @returns {mediaplayer}
579
- */
580
- seek(time, internal) {
581
- if (this._canPlay()) {
582
- this._updatePosition(time, internal);
562
+ this._setState('canplay', true);
583
563
 
584
- this.execute('seek', this.position);
564
+ this._setState('canpause', this.config.canPause);
585
565
 
586
- if (!this.is('ready')) {
587
- this.autoStartAt = this.position;
588
- }
566
+ this._setState('canseek', this.config.canSeek);
589
567
 
590
- this.loop = !!this.config.loop;
591
- }
568
+ this._setState('loading', false);
569
+ },
592
570
 
593
- return this;
594
- },
571
+ /**
572
+ * Sets the start position inside the media
573
+ * @param {Number} time - The start position in seconds
574
+ * @param {*} [internal] - Internal use
575
+ * @returns {mediaplayer}
576
+ */
577
+ seek: function seek(time, internal) {
578
+ if (this._canPlay()) {
579
+ this._updatePosition(time, internal);
595
580
 
596
- /**
597
- * Plays the media
598
- * @param {Number} [time] - An optional start position in seconds
599
- * @returns {mediaplayer}
600
- */
601
- play(time) {
602
- if (this._canPlay()) {
603
- if (typeof time !== 'undefined') {
604
- this.seek(time);
605
- }
581
+ this.execute('seek', this.position);
606
582
 
607
- this.execute('play');
583
+ if (!this.is('ready')) {
584
+ this.autoStartAt = this.position;
585
+ }
608
586
 
609
- if (!this.is('ready')) {
610
- this.autoStart = true;
611
- }
587
+ this.loop = !!this.config.loop;
588
+ }
612
589
 
613
- this.loop = !!this.config.loop;
590
+ return this;
591
+ },
614
592
 
615
- if (this.timerId) {
616
- cancelAnimationFrame(this.timerId);
617
- }
593
+ /**
594
+ * Plays the media
595
+ * @param {Number} [time] - An optional start position in seconds
596
+ * @returns {mediaplayer}
597
+ */
598
+ play: function play(time) {
599
+ if (this._canPlay()) {
600
+ if (typeof time !== 'undefined') {
601
+ this.seek(time);
618
602
  }
619
603
 
620
- return this;
621
- },
604
+ this.execute('play');
622
605
 
623
- /**
624
- * Pauses the media
625
- * @param {Number} [time] - An optional time position in seconds
626
- * @returns {mediaplayer}
627
- */
628
- pause(time) {
629
- if (this._canPause()) {
630
- if (typeof time !== 'undefined') {
631
- this.seek(time);
632
- }
606
+ if (!this.is('ready')) {
607
+ this.autoStart = true;
608
+ }
633
609
 
634
- this.execute('pause');
610
+ this.loop = !!this.config.loop;
635
611
 
636
- if (!this.is('ready')) {
637
- this.autoStart = false;
638
- }
612
+ if (this.timerId) {
613
+ cancelAnimationFrame(this.timerId);
639
614
  }
615
+ }
640
616
 
641
- return this;
642
- },
617
+ return this;
618
+ },
643
619
 
644
- /**
645
- * Resumes the media
646
- * @returns {mediaplayer}
647
- */
648
- resume() {
649
- if (this._canResume()) {
650
- this.play();
620
+ /**
621
+ * Pauses the media
622
+ * @param {Number} [time] - An optional time position in seconds
623
+ * @returns {mediaplayer}
624
+ */
625
+ pause: function pause(time) {
626
+ if (this._canPause()) {
627
+ if (typeof time !== 'undefined') {
628
+ this.seek(time);
651
629
  }
652
630
 
653
- return this;
654
- },
655
-
656
- /**
657
- * Stops the playback
658
- * @returns {mediaplayer}
659
- */
660
- stop() {
661
- this.loop = false;
662
- this.execute('stop');
631
+ this.execute('pause');
663
632
 
664
633
  if (!this.is('ready')) {
665
634
  this.autoStart = false;
666
635
  }
636
+ }
667
637
 
668
- return this;
669
- },
670
-
671
- /**
672
- * Starts the media
673
- * @returns {mediaplayer}
674
- */
675
- start() {
676
- this._setState('preview', true);
677
-
678
- this._setState('loading', true);
638
+ return this;
639
+ },
679
640
 
641
+ /**
642
+ * Resumes the media
643
+ * @returns {mediaplayer}
644
+ */
645
+ resume: function resume() {
646
+ if (this._canResume()) {
680
647
  this.play();
681
- },
682
-
683
- /**
684
- * Restarts the media from the beginning
685
- * @returns {mediaplayer}
686
- */
687
- restart() {
688
- this.play(0);
689
- return this;
690
- },
648
+ }
691
649
 
692
- /**
693
- * Rewind the media to the beginning
694
- * @returns {mediaplayer}
695
- */
696
- rewind() {
697
- this.seek(0);
698
- return this;
699
- },
650
+ return this;
651
+ },
700
652
 
701
- /**
702
- * Mutes the media
703
- * @param {Boolean} [state] - A flag to set the mute state (default: true)
704
- * @returns {mediaplayer}
705
- */
706
- mute(state) {
707
- if (typeof state === 'undefined') {
708
- state = true;
709
- }
653
+ /**
654
+ * Stops the playback
655
+ * @returns {mediaplayer}
656
+ */
657
+ stop: function stop() {
658
+ this.loop = false;
659
+ this.execute('stop');
710
660
 
711
- this.execute('mute', state);
661
+ if (!this.is('ready')) {
662
+ this.autoStart = false;
663
+ }
712
664
 
713
- this._setState('muted', state);
665
+ return this;
666
+ },
714
667
 
715
- if (!this.is('ready')) {
716
- this.startMuted = state;
717
- }
668
+ /**
669
+ * Starts the media
670
+ * @returns {mediaplayer}
671
+ */
672
+ start: function start() {
673
+ this._setState('preview', true);
718
674
 
719
- return this;
720
- },
675
+ this._setState('loading', true);
721
676
 
722
- /**
723
- * Restore the sound of the media after a mute
724
- * @returns {mediaplayer}
725
- */
726
- unmute() {
727
- this.mute(false);
728
- return this;
729
- },
677
+ this.play();
678
+ },
730
679
 
731
- /**
732
- * Sets the sound volume of the media being played
733
- * @param {Number} value - A value between 0 and 100
734
- * @param {*} [internal] - Internal use
735
- * @returns {mediaplayer}
736
- */
737
- setVolume(value, internal) {
738
- this._updateVolume(value, internal);
680
+ /**
681
+ * Restarts the media from the beginning
682
+ * @returns {mediaplayer}
683
+ */
684
+ restart: function restart() {
685
+ this.play(0);
686
+ return this;
687
+ },
739
688
 
740
- this.execute('setVolume', this.volume);
741
- return this;
742
- },
689
+ /**
690
+ * Rewind the media to the beginning
691
+ * @returns {mediaplayer}
692
+ */
693
+ rewind: function rewind() {
694
+ this.seek(0);
695
+ return this;
696
+ },
743
697
 
744
- /**
745
- * Gets the sound volume applied to the media being played
746
- * @returns {Number} Returns a value between 0 and 100
747
- */
748
- getVolume() {
749
- return this.volume;
750
- },
698
+ /**
699
+ * Mutes the media
700
+ * @param {Boolean} [state] - A flag to set the mute state (default: true)
701
+ * @returns {mediaplayer}
702
+ */
703
+ mute: function mute(state) {
704
+ if (typeof state === 'undefined') {
705
+ state = true;
706
+ }
751
707
 
752
- /**
753
- * Gets the current displayed position inside the media
754
- * @returns {Number}
755
- */
756
- getPosition() {
757
- return this.position;
758
- },
708
+ this.execute('mute', state);
759
709
 
760
- /**
761
- * Gets the duration of the media
762
- * @returns {Number}
763
- */
764
- getDuration() {
765
- return this.duration;
766
- },
710
+ this._setState('muted', state);
767
711
 
768
- /**
769
- * Gets the number of times the media has been played
770
- * @returns {Number}
771
- */
772
- getTimesPlayed() {
773
- return this.timesPlayed;
774
- },
712
+ if (!this.is('ready')) {
713
+ this.startMuted = state;
714
+ }
775
715
 
776
- /**
777
- * Gets the type of player
778
- * @returns {String}
779
- */
780
- getType() {
781
- return this.type;
782
- },
716
+ return this;
717
+ },
783
718
 
784
- /**
785
- * Gets the DOM container
786
- * @returns {jQuery}
787
- */
788
- getContainer() {
789
- if (!this.$container && this.$component) {
790
- let $container = this.$component.parent();
719
+ /**
720
+ * Restore the sound of the media after a mute
721
+ * @returns {mediaplayer}
722
+ */
723
+ unmute: function unmute() {
724
+ this.mute(false);
725
+ return this;
726
+ },
791
727
 
792
- if ($container.length) {
793
- this.$container = $container;
794
- }
795
- }
728
+ /**
729
+ * Sets the sound volume of the media being played
730
+ * @param {Number} value - A value between 0 and 100
731
+ * @param {*} [internal] - Internal use
732
+ * @returns {mediaplayer}
733
+ */
734
+ setVolume: function setVolume(value, internal) {
735
+ this._updateVolume(value, internal);
796
736
 
797
- return this.$container;
798
- },
737
+ this.execute('setVolume', this.volume);
738
+ return this;
739
+ },
799
740
 
800
- /**
801
- * Gets the underlying DOM element
802
- * @returns {jQuery}
803
- */
804
- getElement() {
805
- return this.$component;
806
- },
741
+ /**
742
+ * Gets the sound volume applied to the media being played
743
+ * @returns {Number} Returns a value between 0 and 100
744
+ */
745
+ getVolume: function getVolume() {
746
+ return this.volume;
747
+ },
807
748
 
808
- /**
809
- * Gets the list of media
810
- * @returns {Array}
811
- */
812
- getSources() {
813
- return this.config.sources.slice();
814
- },
749
+ /**
750
+ * Gets the current displayed position inside the media
751
+ * @returns {Number}
752
+ */
753
+ getPosition: function getPosition() {
754
+ return this.position;
755
+ },
815
756
 
816
- /**
817
- * Sets the media source. If a source has been already set, it will be replaced.
818
- * @param {String|Object} src - The media URL, or an object containing the source and the type
819
- * @param {Function} [callback] - A function called to provide the added media source object
820
- * @returns {mediaplayer}
821
- */
822
- setSource(src, callback) {
823
- this._getSource(src, source => {
824
- this.config.sources = [source];
757
+ /**
758
+ * Gets the duration of the media
759
+ * @returns {Number}
760
+ */
761
+ getDuration: function getDuration() {
762
+ return this.duration;
763
+ },
825
764
 
826
- if (this.is('rendered')) {
827
- this.player.setMedia(source.src, source.type);
828
- }
765
+ /**
766
+ * Gets the number of times the media has been played
767
+ * @returns {Number}
768
+ */
769
+ getTimesPlayed: function getTimesPlayed() {
770
+ return this.timesPlayed;
771
+ },
829
772
 
830
- if (callback) {
831
- callback.call(this, source);
832
- }
833
- });
773
+ /**
774
+ * Gets the type of player
775
+ * @returns {String}
776
+ */
777
+ getType: function getType() {
778
+ return this.type;
779
+ },
834
780
 
835
- return this;
836
- },
781
+ /**
782
+ * Gets the DOM container
783
+ * @returns {jQuery}
784
+ */
785
+ getContainer: function getContainer() {
786
+ if (!this.$container && this.$component) {
787
+ var $container = this.$component.parent();
837
788
 
838
- /**
839
- * Adds a media source.
840
- * @param {String|Object} src - The media URL, or an object containing the source and the type
841
- * @param {Function} [callback] - A function called to provide the added media source object
842
- * @returns {mediaplayer}
843
- */
844
- addSource(src, callback) {
845
- this._getSource(src, source => {
846
- this.config.sources.push(source);
789
+ if ($container.length) {
790
+ this.$container = $container;
791
+ }
792
+ }
847
793
 
848
- if (this.is('rendered')) {
849
- this.player.addMedia(source.src, source.type);
850
- }
794
+ return this.$container;
795
+ },
851
796
 
852
- if (callback) {
853
- callback.call(this, source);
854
- }
855
- });
797
+ /**
798
+ * Gets the underlying DOM element
799
+ * @returns {jQuery}
800
+ */
801
+ getElement: function getElement() {
802
+ return this.$component;
803
+ },
856
804
 
857
- return this;
858
- },
805
+ /**
806
+ * Gets the list of media
807
+ * @returns {Array}
808
+ */
809
+ getSources: function getSources() {
810
+ return this.config.sources.slice();
811
+ },
859
812
 
860
- /**
861
- * Tells if the media is in a particular state
862
- * @param {String} state
863
- * @returns {Boolean}
864
- */
865
- is(state) {
866
- return !!this.config.is[state];
867
- },
813
+ /**
814
+ * Sets the media source. If a source has been already set, it will be replaced.
815
+ * @param {String|Object} src - The media URL, or an object containing the source and the type
816
+ * @param {Function} [callback] - A function called to provide the added media source object
817
+ * @returns {mediaplayer}
818
+ */
819
+ setSource: function setSource(src, callback) {
820
+ var _this2 = this;
868
821
 
869
- /**
870
- * Changes the size of the player
871
- * @param {Number} width
872
- * @param {Number} height
873
- * @returns {mediaplayer}
874
- */
875
- resize(width, height) {
876
- if (isResponsiveSize(width) && !isResponsiveSize(height) || this.is('youtube')) {
877
- // responsive width height should be auto
878
- // for youtube iframe height is limited by ration
879
- height = 'auto';
822
+ this._getSource(src, function (source) {
823
+ _this2.config.sources = [source];
824
+
825
+ if (_this2.is('rendered')) {
826
+ _this2.player.setMedia(source.src, source.type);
880
827
  }
881
828
 
882
- this.execute('setSize', width, height);
883
- return this;
884
- },
829
+ if (callback) {
830
+ callback.call(_this2, source);
831
+ }
832
+ });
885
833
 
886
- /**
887
- * Enables the media player
888
- * @returns {mediaplayer}
889
- */
890
- enable() {
891
- this._fromState('disabled');
834
+ return this;
835
+ },
892
836
 
893
- return this;
894
- },
837
+ /**
838
+ * Adds a media source.
839
+ * @param {String|Object} src - The media URL, or an object containing the source and the type
840
+ * @param {Function} [callback] - A function called to provide the added media source object
841
+ * @returns {mediaplayer}
842
+ */
843
+ addSource: function addSource(src, callback) {
844
+ var _this3 = this;
895
845
 
896
- /**
897
- * Disables the media player
898
- * @returns {mediaplayer}
899
- */
900
- disable() {
901
- this._toState('disabled');
846
+ this._getSource(src, function (source) {
847
+ _this3.config.sources.push(source);
902
848
 
903
- this.trigger('disabled');
904
- return this;
905
- },
849
+ if (_this3.is('rendered')) {
850
+ _this3.player.addMedia(source.src, source.type);
851
+ }
906
852
 
907
- /**
908
- * Shows the media player
909
- * @returns {mediaplayer}
910
- */
911
- show() {
912
- this._fromState('hidden');
853
+ if (callback) {
854
+ callback.call(_this3, source);
855
+ }
856
+ });
913
857
 
914
- return this;
915
- },
858
+ return this;
859
+ },
916
860
 
917
- /**
918
- * hides the media player
919
- * @returns {mediaplayer}
920
- */
921
- hide() {
922
- this._toState('hidden');
861
+ /**
862
+ * Tells if the media is in a particular state
863
+ * @param {String} state
864
+ * @returns {Boolean}
865
+ */
866
+ is: function is(state) {
867
+ return !!this.config.is[state];
868
+ },
923
869
 
924
- return this;
925
- },
870
+ /**
871
+ * Changes the size of the player
872
+ * @param {Number} width
873
+ * @param {Number} height
874
+ * @returns {mediaplayer}
875
+ */
876
+ resize: function resize(width, height) {
877
+ if (isResponsiveSize(width) && !isResponsiveSize(height) || this.is('youtube')) {
878
+ // responsive width height should be auto
879
+ // for youtube iframe height is limited by ration
880
+ height = 'auto';
881
+ }
926
882
 
927
- /**
928
- * get media original size
929
- * @returns {Object}
930
- */
931
- getMediaOriginalSize() {
932
- if (this.is('youtube')) {
933
- return defaults.youtube;
934
- }
883
+ this.execute('setSize', width, height);
884
+ return this;
885
+ },
935
886
 
936
- if (this.is('video') && this.player) {
937
- return this.player.getMediaSize();
938
- }
887
+ /**
888
+ * Enables the media player
889
+ * @returns {mediaplayer}
890
+ */
891
+ enable: function enable() {
892
+ this._fromState('disabled');
939
893
 
940
- return {};
941
- },
894
+ return this;
895
+ },
942
896
 
943
- /**
944
- * Ensures the right media type is set
945
- * @param {String} type
946
- * @private
947
- */
948
- _setType(type) {
949
- if (type.indexOf('youtube') !== -1) {
950
- this.type = 'youtube';
951
- } else if (type.indexOf('audio') === 0) {
952
- this.type = 'audio';
953
- } else {
954
- this.type = 'video';
955
- }
956
- },
897
+ /**
898
+ * Disables the media player
899
+ * @returns {mediaplayer}
900
+ */
901
+ disable: function disable() {
902
+ this._toState('disabled');
957
903
 
958
- /**
959
- * Ensures the type is correctly applied
960
- * @private
961
- */
962
- _initType() {
963
- const is = this.config.is;
964
- is.youtube = 'youtube' === this.type;
965
- is.video = 'video' === this.type || 'youtube' === this.type;
966
- is.audio = 'audio' === this.type;
967
- },
904
+ this.trigger('disabled');
905
+ return this;
906
+ },
968
907
 
969
- /**
970
- * Gets a source descriptor.
971
- * @param {String|Object} src - The media URL, or an object containing the source and the type
972
- * @param {Function} callback - A function called to provide the media source object
973
- */
974
- _getSource(src, callback) {
975
- let source;
908
+ /**
909
+ * Shows the media player
910
+ * @returns {mediaplayer}
911
+ */
912
+ show: function show() {
913
+ this._fromState('hidden');
976
914
 
977
- const done = () => {
978
- if (needTypeAdjust(source.type)) {
979
- source.type = getAdjustedType(source);
980
- }
915
+ return this;
916
+ },
981
917
 
982
- callback.call(this, source);
983
- };
918
+ /**
919
+ * hides the media player
920
+ * @returns {mediaplayer}
921
+ */
922
+ hide: function hide() {
923
+ this._toState('hidden');
984
924
 
985
- if (_.isString(src)) {
986
- source = {
987
- src: src
988
- };
989
- } else {
990
- source = _.clone(src);
991
- }
925
+ return this;
926
+ },
992
927
 
993
- if (!source.type) {
994
- if (this.is('youtube')) {
995
- source.type = defaults.type;
996
- } else if (this.config.mimeType) {
997
- source.type = this.config.mimeType;
998
- }
999
- }
928
+ /**
929
+ * get media original size
930
+ * @returns {Object}
931
+ */
932
+ getMediaOriginalSize: function getMediaOriginalSize() {
933
+ if (this.is('youtube')) {
934
+ return defaults.youtube;
935
+ }
1000
936
 
1001
- if (!source.type) {
1002
- mimetype.getResourceType(source.src, (err, type) => {
1003
- if (err) {
1004
- type = defaults.type;
1005
- }
937
+ if (this.is('video') && this.player) {
938
+ return this.player.getMediaSize();
939
+ }
1006
940
 
1007
- source.type = type;
1008
- done();
1009
- });
1010
- } else {
1011
- done();
1012
- }
1013
- },
941
+ return {};
942
+ },
1014
943
 
1015
- /**
1016
- * Ensures the sources are correctly set
1017
- * @param {Function} callback - A function called once all sources have been initialized
1018
- * @private
1019
- */
1020
- _initSources(callback) {
1021
- const sources = configToSources(this.config);
1022
- this.config.sources = [];
1023
- async.each(sources, (source, cb) => {
1024
- this.addSource(source, src => cb(null, src));
1025
- }, callback);
1026
- },
944
+ /**
945
+ * Ensures the right media type is set
946
+ * @param {String} type
947
+ * @private
948
+ */
949
+ _setType: function _setType(type) {
950
+ if (type.indexOf('youtube') !== -1) {
951
+ this.type = 'youtube';
952
+ } else if (type.indexOf('audio') === 0) {
953
+ this.type = 'audio';
954
+ } else {
955
+ this.type = 'video';
956
+ }
957
+ },
1027
958
 
1028
- /**
1029
- * Installs the events manager onto the instance
1030
- * @private
1031
- */
1032
- _initEvents() {
1033
- eventifier(this);
1034
- const triggerEvent = this.trigger;
959
+ /**
960
+ * Ensures the type is correctly applied
961
+ * @private
962
+ */
963
+ _initType: function _initType() {
964
+ var is = this.config.is;
965
+ is.youtube = 'youtube' === this.type;
966
+ is.video = 'video' === this.type || 'youtube' === this.type;
967
+ is.audio = 'audio' === this.type;
968
+ },
1035
969
 
1036
- this.trigger = function trigger(eventName) {
1037
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1038
- args[_key - 1] = arguments[_key];
1039
- }
970
+ /**
971
+ * Gets a source descriptor.
972
+ * @param {String|Object} src - The media URL, or an object containing the source and the type
973
+ * @param {Function} callback - A function called to provide the media source object
974
+ */
975
+ _getSource: function _getSource(src, callback) {
976
+ var _this4 = this;
1040
977
 
1041
- if (this.$component) {
1042
- this.$component.trigger(eventName + ns, ...args);
1043
- }
978
+ var source;
1044
979
 
1045
- return triggerEvent.call(this, eventName, ...args);
980
+ var done = function done() {
981
+ if (needTypeAdjust(source.type)) {
982
+ source.type = getAdjustedType(source);
983
+ }
984
+
985
+ callback.call(_this4, source);
986
+ };
987
+
988
+ if (_.isString(src)) {
989
+ source = {
990
+ src: src
1046
991
  };
1047
- },
992
+ } else {
993
+ source = _.clone(src);
994
+ }
1048
995
 
1049
- /**
1050
- * Ensures the right size is set according to the media type
1051
- * @private
1052
- */
1053
- _initSize() {
1054
- const type = this.is('video') ? 'video' : 'audio';
1055
- const mediaConfig = defaults[type] || defaults.video;
1056
- this.config.width = this.config.width || mediaConfig.width;
1057
- this.config.height = this.config.height || mediaConfig.height;
1058
-
1059
- if (isResponsiveSize(this.config.width) && !isResponsiveSize(this.config.height) || this.is('youtube')) {
1060
- // responsive width height should be auto
1061
- // for youtube iframe height is limited by ration
1062
- this.config.height = 'auto';
996
+ if (!source.type) {
997
+ if (this.is('youtube')) {
998
+ source.type = defaults.type;
999
+ } else if (this.config.mimeType) {
1000
+ source.type = this.config.mimeType;
1063
1001
  }
1064
- },
1065
-
1066
- /**
1067
- * Initializes the right player instance
1068
- * @private
1069
- */
1070
- _initPlayer() {
1071
- const playerFactory = players[this.type];
1072
- let error;
1073
-
1074
- if (support.canPlay(this.type)) {
1075
- if (_.isFunction(playerFactory)) {
1076
- const playerConfig = {
1077
- type: this.getType(),
1078
- sources: this.getSources(),
1079
- preview: this.config.preview,
1080
- debug: this.config.debug,
1081
- stalledDetectionDelay: this.config.stalledDetectionDelay
1082
- };
1083
- this.player = playerFactory(this.$player, playerConfig).on('resize', (width, height) => {
1084
- if (this.$component) {
1085
- this.$component.width(width).height(height);
1086
- }
1087
- }).on('ready', () => this._onReady()).on('play', () => this._onPlay()).on('pause', () => this._onPause()).on('timeupdate', () => this._onTimeUpdate()).on('stalled', () => this._onStalled()).on('playing', () => this._onPlaying()).on('end', () => this._onEnd()).on('error', () => this._onError());
1088
- }
1002
+ }
1089
1003
 
1090
- if (this.player) {
1091
- error = !this.player.init();
1092
- } else {
1093
- error = true;
1004
+ if (!source.type) {
1005
+ mimetype.getResourceType(source.src, function (err, type) {
1006
+ if (err) {
1007
+ type = defaults.type;
1094
1008
  }
1095
- } else {
1096
- error = true;
1097
- }
1098
1009
 
1099
- this._setState('error', error);
1010
+ source.type = type;
1011
+ done();
1012
+ });
1013
+ } else {
1014
+ done();
1015
+ }
1016
+ },
1100
1017
 
1101
- this._setState('nogui', !support.canControl());
1018
+ /**
1019
+ * Ensures the sources are correctly set
1020
+ * @param {Function} callback - A function called once all sources have been initialized
1021
+ * @private
1022
+ */
1023
+ _initSources: function _initSources(callback) {
1024
+ var _this5 = this;
1025
+
1026
+ var sources = configToSources(this.config);
1027
+ this.config.sources = [];
1028
+ async.each(sources, function (source, cb) {
1029
+ _this5.addSource(source, function (src) {
1030
+ return cb(null, src);
1031
+ });
1032
+ }, callback);
1033
+ },
1102
1034
 
1103
- this._setState('preview', this.config.preview);
1035
+ /**
1036
+ * Installs the events manager onto the instance
1037
+ * @private
1038
+ */
1039
+ _initEvents: function _initEvents() {
1040
+ eventifier(this);
1041
+ var triggerEvent = this.trigger;
1104
1042
 
1105
- this._setState('loading', !error);
1043
+ this.trigger = function trigger(eventName) {
1044
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1045
+ args[_key - 1] = arguments[_key];
1046
+ }
1106
1047
 
1107
- if (error) {
1108
- this._setState('ready', true);
1048
+ if (this.$component) {
1049
+ var _this$$component;
1109
1050
 
1110
- this.trigger('ready');
1051
+ (_this$$component = this.$component).trigger.apply(_this$$component, [eventName + ns].concat(args));
1111
1052
  }
1112
- },
1113
1053
 
1114
- /**
1115
- * Initializes the player state
1116
- * @private
1117
- */
1118
- _initState() {
1119
- let isCORS = false;
1120
- let page;
1054
+ return triggerEvent.call.apply(triggerEvent, [this, eventName].concat(args));
1055
+ };
1056
+ },
1121
1057
 
1122
- if (!this.is('youtube')) {
1123
- page = new UrlParser(window.location);
1124
- isCORS = _.some(this.config.sources, source => !page.sameDomain(source.src));
1125
- }
1058
+ /**
1059
+ * Ensures the right size is set according to the media type
1060
+ * @private
1061
+ */
1062
+ _initSize: function _initSize() {
1063
+ var type = this.is('video') ? 'video' : 'audio';
1064
+ var mediaConfig = defaults[type] || defaults.video;
1065
+ this.config.width = this.config.width || mediaConfig.width;
1066
+ this.config.height = this.config.height || mediaConfig.height;
1067
+
1068
+ if (isResponsiveSize(this.config.width) && !isResponsiveSize(this.config.height) || this.is('youtube')) {
1069
+ // responsive width height should be auto
1070
+ // for youtube iframe height is limited by ration
1071
+ this.config.height = 'auto';
1072
+ }
1073
+ },
1126
1074
 
1127
- this._setState('cors', isCORS);
1075
+ /**
1076
+ * Initializes the right player instance
1077
+ * @private
1078
+ */
1079
+ _initPlayer: function _initPlayer() {
1080
+ var _this6 = this;
1081
+
1082
+ var playerFactory = players[this.type];
1083
+ var error;
1084
+
1085
+ if (support.canPlay(this.type)) {
1086
+ if (_.isFunction(playerFactory)) {
1087
+ var playerConfig = {
1088
+ type: this.getType(),
1089
+ sources: this.getSources(),
1090
+ preview: this.config.preview,
1091
+ debug: this.config.debug,
1092
+ stalledDetectionDelay: this.config.stalledDetectionDelay
1093
+ };
1094
+ this.player = playerFactory(this.$player, playerConfig).on('resize', function (width, height) {
1095
+ if (_this6.$component) {
1096
+ _this6.$component.width(width).height(height);
1097
+ }
1098
+ }).on('ready', function () {
1099
+ return _this6._onReady();
1100
+ }).on('play', function () {
1101
+ return _this6._onPlay();
1102
+ }).on('pause', function () {
1103
+ return _this6._onPause();
1104
+ }).on('timeupdate', function () {
1105
+ return _this6._onTimeUpdate();
1106
+ }).on('stalled', function () {
1107
+ return _this6._onStalled();
1108
+ }).on('playing', function () {
1109
+ return _this6._onPlaying();
1110
+ }).on('end', function () {
1111
+ return _this6._onEnd();
1112
+ }).on('error', function () {
1113
+ return _this6._onError();
1114
+ });
1115
+ }
1128
1116
 
1129
- this._setState('ready', false);
1130
- },
1117
+ if (this.player) {
1118
+ error = !this.player.init();
1119
+ } else {
1120
+ error = true;
1121
+ }
1122
+ } else {
1123
+ error = true;
1124
+ }
1131
1125
 
1132
- /**
1133
- * Resets the internals attributes
1134
- * @private
1135
- */
1136
- _reset() {
1137
- this.config.is = {};
1126
+ this._setState('error', error);
1138
1127
 
1139
- this._initType();
1128
+ this._setState('nogui', !support.canControl());
1140
1129
 
1141
- this.$component = null;
1142
- this.$container = null;
1143
- this.$player = null;
1144
- this.$controls = null;
1145
- this.$seek = null;
1146
- this.$seekSlider = null;
1147
- this.$sound = null;
1148
- this.$volume = null;
1149
- this.$volumeControl = null;
1150
- this.$volumeSlider = null;
1151
- this.$position = null;
1152
- this.$duration = null;
1153
- this.player = null;
1154
- this.duration = 0;
1155
- this.position = 0;
1156
- this.timesPlayed = 0;
1157
- this.volume = this.config.volume;
1158
- this.autoStart = this.config.autoStart;
1159
- this.autoStartAt = this.config.autoStartAt;
1160
- this.startMuted = this.config.startMuted;
1161
- },
1130
+ this._setState('preview', this.config.preview);
1162
1131
 
1163
- /**
1164
- * Builds the DOM content
1165
- * @private
1166
- */
1167
- _buildDom() {
1168
- const configForTemplate = _.clone(this.config);
1169
-
1170
- configForTemplate.type = this.type;
1171
- this.$component = $$1(playerTpl(configForTemplate));
1172
- this.$player = this.$component.find('.player');
1173
- this.$controls = this.$component.find('.controls');
1174
- this.$seek = this.$controls.find('.seek .slider');
1175
- this.$sound = this.$controls.find('.sound');
1176
- this.$volumeControl = this.$controls.find('.volume');
1177
- this.$volume = this.$controls.find('.volume .slider');
1178
- this.$position = this.$controls.find('[data-control="time-cur"]');
1179
- this.$duration = this.$controls.find('[data-control="time-end"]');
1180
- this.$volumeSlider = this._renderSlider(this.$volume, this.volume, volumeMin, volumeMax, true);
1181
- },
1132
+ this._setState('loading', !error);
1182
1133
 
1183
- /**
1184
- * Renders a slider onto an element
1185
- * @param {jQuery} $elt - The element on which renders the slider
1186
- * @param {Number} [value] - The current value of the slider
1187
- * @param {Number} [min] - The min value of the slider
1188
- * @param {Number} [max] - The max value of the slider
1189
- * @param {Boolean} [vertical] - Tells if the slider must be vertical
1190
- * @returns {jQuery} - Returns the element
1191
- * @private
1192
- */
1193
- _renderSlider($elt, value, min, max, vertical) {
1194
- let orientation, direction;
1134
+ if (error) {
1135
+ this._setState('ready', true);
1195
1136
 
1196
- if (vertical) {
1197
- orientation = 'vertical';
1198
- direction = 'rtl';
1199
- } else {
1200
- orientation = 'horizontal';
1201
- direction = 'ltr';
1202
- }
1137
+ this.trigger('ready');
1138
+ }
1139
+ },
1203
1140
 
1204
- return $elt.noUiSlider({
1205
- start: ensureNumber(value) || 0,
1206
- step: 1,
1207
- connect: 'lower',
1208
- orientation: orientation,
1209
- direction: direction,
1210
- animate: true,
1211
- range: {
1212
- min: ensureNumber(min) || 0,
1213
- max: ensureNumber(max) || 0
1214
- }
1141
+ /**
1142
+ * Initializes the player state
1143
+ * @private
1144
+ */
1145
+ _initState: function _initState() {
1146
+ var isCORS = false;
1147
+ var page;
1148
+
1149
+ if (!this.is('youtube')) {
1150
+ page = new UrlParser(window.location);
1151
+ isCORS = _.some(this.config.sources, function (source) {
1152
+ return !page.sameDomain(source.src);
1215
1153
  });
1216
- },
1154
+ }
1217
1155
 
1218
- /**
1219
- * Destroys a slider bound to an element
1220
- * @param {jQuery} $elt
1221
- * @private
1222
- */
1223
- _destroySlider($elt) {
1224
- if ($elt) {
1225
- $elt.get(0).destroy();
1226
- }
1227
- },
1156
+ this._setState('cors', isCORS);
1228
1157
 
1229
- /**
1230
- * Binds events onto the rendered player
1231
- * @private
1232
- */
1233
- _bindEvents() {
1234
- let overing = false;
1235
- this.$component.on(`contextmenu${ns}`, event => event.preventDefault());
1236
- this.$controls.on(`click${ns}`, '.action', event => {
1237
- const $target = $$1(event.target);
1238
- const $action = $target.closest('.action');
1239
- const id = $action.data('control');
1240
-
1241
- if (_.isFunction(this[id])) {
1242
- this[id]();
1243
- }
1244
- });
1245
- this.$player.on(`click${ns}`, event => {
1246
- const $target = $$1(event.target);
1247
- const $action = $target.closest('.action'); // if action was clicked
1158
+ this._setState('ready', false);
1159
+ },
1248
1160
 
1249
- if ($action.length) {
1250
- const id = $action.data('control');
1161
+ /**
1162
+ * Resets the internals attributes
1163
+ * @private
1164
+ */
1165
+ _reset: function _reset() {
1166
+ this.config.is = {};
1167
+
1168
+ this._initType();
1169
+
1170
+ this.$component = null;
1171
+ this.$container = null;
1172
+ this.$player = null;
1173
+ this.$controls = null;
1174
+ this.$seek = null;
1175
+ this.$seekSlider = null;
1176
+ this.$sound = null;
1177
+ this.$volume = null;
1178
+ this.$volumeControl = null;
1179
+ this.$volumeSlider = null;
1180
+ this.$position = null;
1181
+ this.$duration = null;
1182
+ this.player = null;
1183
+ this.duration = 0;
1184
+ this.position = 0;
1185
+ this.timesPlayed = 0;
1186
+ this.volume = this.config.volume;
1187
+ this.autoStart = this.config.autoStart;
1188
+ this.autoStartAt = this.config.autoStartAt;
1189
+ this.startMuted = this.config.startMuted;
1190
+ },
1251
1191
 
1252
- if (_.isFunction(this[id])) {
1253
- this[id]();
1254
- }
1255
- } else {
1256
- // default action is toggle play
1257
- if (this.is('playing')) {
1258
- this.pause();
1259
- } else {
1260
- this.play();
1261
- }
1262
- }
1263
- });
1264
- this.$seek.on(`change${ns}`, (event, value) => {
1265
- this.seek(value, true);
1266
- });
1267
- $$1(document).on(`updateVolume${ns}`, (event, value) => {
1268
- this.setVolume(value);
1269
- });
1270
- this.$volume.on(`change${ns}`, (event, value) => {
1271
- this.unmute();
1272
- $$1(document).trigger(`updateVolume${ns}`, value);
1273
- this.setVolume(value, true);
1274
- });
1275
- this.$sound.on(`mouseover${ns}`, 'a', () => {
1276
- let position;
1277
-
1278
- if (!overing && !this.$volumeControl.hasClass('up') && !this.$volumeControl.hasClass('down')) {
1279
- overing = true;
1280
- position = this.$controls[0].getBoundingClientRect();
1281
-
1282
- if (position && position.top && position.top < volumePositionThreshold) {
1283
- this.$volumeControl.addClass('down');
1284
- } else {
1285
- this.$volumeControl.addClass('up');
1286
- } //close the volume control after 15s
1287
-
1288
-
1289
- this.overingTimer = _.delay(() => {
1290
- if (this.$volumeControl) {
1291
- this.$volumeControl.removeClass('up down');
1292
- }
1293
-
1294
- overing = false;
1295
- }, 15000);
1296
- this.$volumeControl.one(`mouseleave${ns}`, () => {
1297
- this.$volumeControl.removeClass('up down');
1298
- overing = false;
1299
- });
1300
- }
1301
- });
1302
- },
1192
+ /**
1193
+ * Builds the DOM content
1194
+ * @private
1195
+ */
1196
+ _buildDom: function _buildDom() {
1197
+ var configForTemplate = _.clone(this.config);
1198
+
1199
+ configForTemplate.type = this.type;
1200
+ this.$component = $$1(playerTpl(configForTemplate));
1201
+ this.$player = this.$component.find('.player');
1202
+ this.$controls = this.$component.find('.controls');
1203
+ this.$seek = this.$controls.find('.seek .slider');
1204
+ this.$sound = this.$controls.find('.sound');
1205
+ this.$volumeControl = this.$controls.find('.volume');
1206
+ this.$volume = this.$controls.find('.volume .slider');
1207
+ this.$position = this.$controls.find('[data-control="time-cur"]');
1208
+ this.$duration = this.$controls.find('[data-control="time-end"]');
1209
+ this.$volumeSlider = this._renderSlider(this.$volume, this.volume, volumeMin, volumeMax, true);
1210
+ },
1303
1211
 
1304
- /**
1305
- * Unbinds events from the rendered player
1306
- * @private
1307
- */
1308
- _unbindEvents() {
1309
- this.$component.off(ns);
1310
- this.$player.off(ns);
1311
- this.$controls.off(ns);
1312
- this.$seek.off(ns);
1313
- this.$volume.off(ns); //if the volume is opened and the player destroyed,
1314
- //prevent the callback to run
1315
-
1316
- if (this.overingTimer) {
1317
- clearTimeout(this.overingTimer);
1318
- }
1212
+ /**
1213
+ * Renders a slider onto an element
1214
+ * @param {jQuery} $elt - The element on which renders the slider
1215
+ * @param {Number} [value] - The current value of the slider
1216
+ * @param {Number} [min] - The min value of the slider
1217
+ * @param {Number} [max] - The max value of the slider
1218
+ * @param {Boolean} [vertical] - Tells if the slider must be vertical
1219
+ * @returns {jQuery} - Returns the element
1220
+ * @private
1221
+ */
1222
+ _renderSlider: function _renderSlider($elt, value, min, max, vertical) {
1223
+ var orientation, direction;
1319
1224
 
1320
- $$1(document).off(ns);
1321
- },
1225
+ if (vertical) {
1226
+ orientation = 'vertical';
1227
+ direction = 'rtl';
1228
+ } else {
1229
+ orientation = 'horizontal';
1230
+ direction = 'ltr';
1231
+ }
1322
1232
 
1323
- /**
1324
- * Updates the volume slider
1325
- * @param {Number} value
1326
- * @private
1327
- */
1328
- _updateVolumeSlider(value) {
1329
- if (this.$volumeSlider) {
1330
- this.$volumeSlider.val(value);
1233
+ return $elt.noUiSlider({
1234
+ start: ensureNumber(value) || 0,
1235
+ step: 1,
1236
+ connect: 'lower',
1237
+ orientation: orientation,
1238
+ direction: direction,
1239
+ animate: true,
1240
+ range: {
1241
+ min: ensureNumber(min) || 0,
1242
+ max: ensureNumber(max) || 0
1331
1243
  }
1332
- },
1333
-
1334
- /**
1335
- * Updates the displayed volume
1336
- * @param {Number} value
1337
- * @param {*} [internal]
1338
- * @private
1339
- */
1340
- _updateVolume(value, internal) {
1341
- this.volume = Math.max(volumeMin, Math.min(volumeMax, parseFloat(value)));
1244
+ });
1245
+ },
1342
1246
 
1343
- this._storeVolume(this.volume);
1247
+ /**
1248
+ * Destroys a slider bound to an element
1249
+ * @param {jQuery} $elt
1250
+ * @private
1251
+ */
1252
+ _destroySlider: function _destroySlider($elt) {
1253
+ if ($elt) {
1254
+ $elt.get(0).destroy();
1255
+ }
1256
+ },
1344
1257
 
1345
- if (!internal) {
1346
- this._updateVolumeSlider(value);
1347
- }
1348
- },
1258
+ /**
1259
+ * Binds events onto the rendered player
1260
+ * @private
1261
+ */
1262
+ _bindEvents: function _bindEvents() {
1263
+ var _this7 = this;
1349
1264
 
1350
- /**
1351
- * Updates the time slider
1352
- * @param {Number} value
1353
- * @private
1354
- */
1355
- _updatePositionSlider(value) {
1356
- if (this.$seekSlider) {
1357
- this.$seekSlider.val(value);
1358
- }
1359
- },
1265
+ var overing = false;
1266
+ this.$component.on("contextmenu".concat(ns), function (event) {
1267
+ return event.preventDefault();
1268
+ });
1269
+ this.$controls.on("click".concat(ns), '.action', function (event) {
1270
+ var $target = $$1(event.target);
1271
+ var $action = $target.closest('.action');
1272
+ var id = $action.data('control');
1360
1273
 
1361
- /**
1362
- * Updates the time label
1363
- * @param {Number} value
1364
- * @private
1365
- */
1366
- _updatePositionLabel(value) {
1367
- if (this.$position) {
1368
- this.$position.text(timerFormat(value));
1274
+ if (_.isFunction(_this7[id])) {
1275
+ _this7[id]();
1369
1276
  }
1370
- },
1277
+ });
1278
+ this.$player.on("click".concat(ns), function (event) {
1279
+ var $target = $$1(event.target);
1280
+ var $action = $target.closest('.action'); // if action was clicked
1371
1281
 
1372
- /**
1373
- * Updates the displayed time position
1374
- * @param {Number} value
1375
- * @param {*} [internal]
1376
- * @private
1377
- */
1378
- _updatePosition(value, internal) {
1379
- this.position = Math.max(0, Math.min(this.duration || +Infinity, parseFloat(value)));
1282
+ if ($action.length) {
1283
+ var id = $action.data('control');
1380
1284
 
1381
- if (!internal && this.duration) {
1382
- this._updatePositionSlider(this.position);
1285
+ if (_.isFunction(_this7[id])) {
1286
+ _this7[id]();
1287
+ }
1288
+ } else {
1289
+ // default action is toggle play
1290
+ if (_this7.is('playing')) {
1291
+ _this7.pause();
1292
+ } else {
1293
+ _this7.play();
1294
+ }
1383
1295
  }
1296
+ });
1297
+ this.$seek.on("change".concat(ns), function (event, value) {
1298
+ _this7.seek(value, true);
1299
+ });
1300
+ $$1(document).on("updateVolume".concat(ns), function (event, value) {
1301
+ _this7.setVolume(value);
1302
+ });
1303
+ this.$volume.on("change".concat(ns), function (event, value) {
1304
+ _this7.unmute();
1384
1305
 
1385
- this._updatePositionLabel(this.position);
1386
- },
1306
+ $$1(document).trigger("updateVolume".concat(ns), value);
1387
1307
 
1388
- /**
1389
- * Updates the duration slider
1390
- * @param {Number} value
1391
- * @private
1392
- */
1393
- _updateDurationSlider(value) {
1394
- if (this.$seekSlider) {
1395
- this._destroySlider(this.$seekSlider);
1396
-
1397
- this.$seekSlider = null;
1398
- }
1308
+ _this7.setVolume(value, true);
1309
+ });
1310
+ this.$sound.on("mouseover".concat(ns), 'a', function () {
1311
+ var position;
1399
1312
 
1400
- if (value && isFinite(value)) {
1401
- this.$seekSlider = this._renderSlider(this.$seek, 0, 0, value);
1402
- this.$seekSlider.attr('disabled', !this.config.canSeek);
1403
- }
1404
- },
1313
+ if (!overing && !_this7.$volumeControl.hasClass('up') && !_this7.$volumeControl.hasClass('down')) {
1314
+ overing = true;
1315
+ position = _this7.$controls[0].getBoundingClientRect();
1405
1316
 
1406
- /**
1407
- * Updates the duration label
1408
- * @param {Number} value
1409
- * @private
1410
- */
1411
- _updateDurationLabel(value) {
1412
- if (this.$duration) {
1413
- if (value && isFinite(value)) {
1414
- this.$duration.text(timerFormat(value)).show();
1317
+ if (position && position.top && position.top < volumePositionThreshold) {
1318
+ _this7.$volumeControl.addClass('down');
1415
1319
  } else {
1416
- this.$duration.hide();
1417
- }
1418
- }
1419
- },
1320
+ _this7.$volumeControl.addClass('up');
1321
+ } //close the volume control after 15s
1420
1322
 
1421
- /**
1422
- * Updates the displayed duration
1423
- * @param {Number|String} value
1424
- * @private
1425
- */
1426
- _updateDuration(value) {
1427
- const duration = Math.abs(parseFloat(value));
1428
1323
 
1429
- if (duration !== this.duration) {
1430
- this.duration = duration;
1324
+ _this7.overingTimer = _.delay(function () {
1325
+ if (_this7.$volumeControl) {
1326
+ _this7.$volumeControl.removeClass('up down');
1327
+ }
1431
1328
 
1432
- this._updateDurationSlider(this.duration);
1329
+ overing = false;
1330
+ }, 15000);
1433
1331
 
1434
- this._updateDurationLabel(this.duration);
1435
- }
1436
- },
1332
+ _this7.$volumeControl.one("mouseleave".concat(ns), function () {
1333
+ _this7.$volumeControl.removeClass('up down');
1437
1334
 
1438
- /**
1439
- * Event called when the media is ready
1440
- * @private
1441
- */
1442
- _onReady() {
1443
- if (this.is('error')) {
1444
- this._setState('error', false);
1335
+ overing = false;
1336
+ });
1445
1337
  }
1338
+ });
1339
+ },
1446
1340
 
1447
- const duration = this.player.getDuration();
1448
- const timePreview = this.config.preview || duration;
1341
+ /**
1342
+ * Unbinds events from the rendered player
1343
+ * @private
1344
+ */
1345
+ _unbindEvents: function _unbindEvents() {
1346
+ this.$component.off(ns);
1347
+ this.$player.off(ns);
1348
+ this.$controls.off(ns);
1349
+ this.$seek.off(ns);
1350
+ this.$volume.off(ns); //if the volume is opened and the player destroyed,
1351
+ //prevent the callback to run
1352
+
1353
+ if (this.overingTimer) {
1354
+ clearTimeout(this.overingTimer);
1355
+ }
1449
1356
 
1450
- if (timePreview) {
1451
- this._updateDuration(duration);
1452
- }
1357
+ $$1(document).off(ns);
1358
+ },
1453
1359
 
1454
- this.setInitialStates();
1455
- /**
1456
- * Triggers a media ready event
1457
- * @event mediaplayer#ready
1458
- */
1360
+ /**
1361
+ * Updates the volume slider
1362
+ * @param {Number} value
1363
+ * @private
1364
+ */
1365
+ _updateVolumeSlider: function _updateVolumeSlider(value) {
1366
+ if (this.$volumeSlider) {
1367
+ this.$volumeSlider.val(value);
1368
+ }
1369
+ },
1459
1370
 
1460
- this.trigger('ready'); // set the initial state
1371
+ /**
1372
+ * Updates the displayed volume
1373
+ * @param {Number} value
1374
+ * @param {*} [internal]
1375
+ * @private
1376
+ */
1377
+ _updateVolume: function _updateVolume(value, internal) {
1378
+ this.volume = Math.max(volumeMin, Math.min(volumeMax, parseFloat(value)));
1461
1379
 
1462
- this.setVolume(this.volume);
1463
- this.mute(!!this.startMuted);
1380
+ this._storeVolume(this.volume);
1464
1381
 
1465
- if (this.autoStartAt) {
1466
- this.seek(this.autoStartAt);
1467
- } else if (this.autoStart) {
1468
- this.play();
1469
- }
1382
+ if (!internal) {
1383
+ this._updateVolumeSlider(value);
1384
+ }
1385
+ },
1470
1386
 
1471
- if (this.config.preview && this.$container && this.config.height && this.config.height !== 'auto') {
1472
- this._setMaxHeight();
1473
- }
1474
- },
1387
+ /**
1388
+ * Updates the time slider
1389
+ * @param {Number} value
1390
+ * @private
1391
+ */
1392
+ _updatePositionSlider: function _updatePositionSlider(value) {
1393
+ if (this.$seekSlider) {
1394
+ this.$seekSlider.val(value);
1395
+ }
1396
+ },
1475
1397
 
1476
- /**
1477
- * Set max height limit for container
1478
- * using by old media items with defined height.
1479
- * @private
1480
- */
1481
- _setMaxHeight() {
1482
- const $video = this.$container.find('video.video');
1483
- const controlsHeight = parseInt(window.getComputedStyle(this.$controls[0]).height);
1484
- const scale = $video.height() / this.config.height;
1485
- const playerWidth = this.$container.find('.player').width();
1486
- const videoWidth = $video.width() / scale;
1487
-
1488
- if (videoWidth > playerWidth) {
1489
- this.execute('setSize', '100%', 'auto');
1490
- } else {
1491
- this.$component.css({
1492
- maxHeight: `${this.config.height + controlsHeight}px`
1493
- });
1494
- this.execute('setSize', Math.floor(videoWidth), 'auto');
1495
- }
1496
- },
1398
+ /**
1399
+ * Updates the time label
1400
+ * @param {Number} value
1401
+ * @private
1402
+ */
1403
+ _updatePositionLabel: function _updatePositionLabel(value) {
1404
+ if (this.$position) {
1405
+ this.$position.text(timerFormat(value));
1406
+ }
1407
+ },
1497
1408
 
1498
- /**
1499
- * Update volume in DBIndex store
1500
- * @param {Number} volume
1501
- * @returns {Promise}
1502
- * @private
1503
- */
1504
- _storeVolume(volume) {
1505
- return store('mediaVolume').then(volumeStore => volumeStore.setItem('volume', volume));
1506
- },
1409
+ /**
1410
+ * Updates the displayed time position
1411
+ * @param {Number} value
1412
+ * @param {*} [internal]
1413
+ * @private
1414
+ */
1415
+ _updatePosition: function _updatePosition(value, internal) {
1416
+ this.position = Math.max(0, Math.min(this.duration || +Infinity, parseFloat(value)));
1507
1417
 
1508
- /**
1509
- * Get volume from DBIndex store
1510
- * @returns {Promise}
1511
- * @private
1512
- */
1513
- _updateVolumeFromStore() {
1514
- return store('mediaVolume').then(volumeStore => volumeStore.getItem('volume')).then(volume => {
1515
- if (_.isNumber(volume)) {
1516
- this.volume = Math.max(volumeMin, Math.min(volumeMax, parseFloat(volume)));
1517
- this.setVolume(this.volume);
1518
- }
1519
- });
1520
- },
1418
+ if (!internal && this.duration) {
1419
+ this._updatePositionSlider(this.position);
1420
+ }
1521
1421
 
1522
- /**
1523
- * Event called when the media throws unrecoverable error
1524
- * @private
1525
- */
1526
- _onError() {
1527
- this._setState('error', true);
1422
+ this._updatePositionLabel(this.position);
1423
+ },
1528
1424
 
1529
- this._setState('loading', false);
1530
- /**
1531
- * Triggers an unrecoverable media error event
1532
- * @event mediaplayer#error
1533
- */
1425
+ /**
1426
+ * Updates the duration slider
1427
+ * @param {Number} value
1428
+ * @private
1429
+ */
1430
+ _updateDurationSlider: function _updateDurationSlider(value) {
1431
+ if (this.$seekSlider) {
1432
+ this._destroySlider(this.$seekSlider);
1534
1433
 
1434
+ this.$seekSlider = null;
1435
+ }
1535
1436
 
1536
- this.trigger('error');
1537
- },
1437
+ if (value && isFinite(value)) {
1438
+ this.$seekSlider = this._renderSlider(this.$seek, 0, 0, value);
1439
+ this.$seekSlider.attr('disabled', !this.config.canSeek);
1440
+ }
1441
+ },
1538
1442
 
1539
- /**
1540
- * Event called when the media is played
1541
- * @private
1542
- */
1543
- _onPlay() {
1544
- this._playingState(true);
1443
+ /**
1444
+ * Updates the duration label
1445
+ * @param {Number} value
1446
+ * @private
1447
+ */
1448
+ _updateDurationLabel: function _updateDurationLabel(value) {
1449
+ if (this.$duration) {
1450
+ if (value && isFinite(value)) {
1451
+ this.$duration.text(timerFormat(value)).show();
1452
+ } else {
1453
+ this.$duration.hide();
1454
+ }
1455
+ }
1456
+ },
1545
1457
 
1546
- this._setState('preview', true);
1547
- /**
1548
- * Triggers a media playback event
1549
- * @event mediaplayer#play
1550
- */
1458
+ /**
1459
+ * Updates the displayed duration
1460
+ * @param {Number|String} value
1461
+ * @private
1462
+ */
1463
+ _updateDuration: function _updateDuration(value) {
1464
+ var duration = Math.abs(parseFloat(value));
1551
1465
 
1466
+ if (duration !== this.duration) {
1467
+ this.duration = duration;
1552
1468
 
1553
- this.trigger('play', this.player && this.player.getMedia());
1554
- },
1469
+ this._updateDurationSlider(this.duration);
1555
1470
 
1556
- /**
1557
- * Event called when the media is paused
1558
- * @private
1559
- */
1560
- _onPause() {
1561
- this._playingState(false);
1562
- /**
1563
- * Triggers a media paused event
1564
- * @event mediaplayer#pause
1565
- */
1471
+ this._updateDurationLabel(this.duration);
1472
+ }
1473
+ },
1566
1474
 
1475
+ /**
1476
+ * Event called when the media is ready
1477
+ * @private
1478
+ */
1479
+ _onReady: function _onReady() {
1480
+ if (this.is('error')) {
1481
+ this._setState('error', false);
1482
+ }
1483
+
1484
+ var duration = this.player.getDuration();
1485
+ var timePreview = this.config.preview || duration;
1567
1486
 
1568
- this.trigger('pause');
1569
- },
1487
+ if (timePreview) {
1488
+ this._updateDuration(duration);
1489
+ }
1570
1490
 
1491
+ this.setInitialStates();
1571
1492
  /**
1572
- * Event called when the media is ended
1573
- * @private
1493
+ * Triggers a media ready event
1494
+ * @event mediaplayer#ready
1574
1495
  */
1575
- _onEnd() {
1576
- this.timesPlayed++;
1577
1496
 
1578
- this._playingState(false, true);
1497
+ this.trigger('ready'); // set the initial state
1579
1498
 
1580
- this._updatePosition(0); // disable when the play limit is reached
1499
+ this.setVolume(this.volume);
1500
+ this.mute(!!this.startMuted);
1581
1501
 
1502
+ if (this.autoStartAt) {
1503
+ this.seek(this.autoStartAt);
1504
+ } else if (this.autoStart) {
1505
+ this.play();
1506
+ }
1582
1507
 
1583
- if (this._playLimitReached()) {
1584
- if (!this.is('disabled')) {
1585
- this.disable();
1586
- }
1587
- /**
1588
- * Triggers a play limit reached event
1589
- * @event mediaplayer#limitreached
1590
- */
1508
+ if (this.config.preview && this.$container && this.config.height && this.config.height !== 'auto') {
1509
+ this._setMaxHeight();
1510
+ }
1511
+ },
1512
+
1513
+ /**
1514
+ * Set max height limit for container
1515
+ * using by old media items with defined height.
1516
+ * @private
1517
+ */
1518
+ _setMaxHeight: function _setMaxHeight() {
1519
+ var $video = this.$container.find('video.video');
1520
+ var controlsHeight = parseInt(window.getComputedStyle(this.$controls[0]).height);
1521
+ var scale = $video.height() / this.config.height;
1522
+ var playerWidth = this.$container.find('.player').width();
1523
+ var videoWidth = $video.width() / scale;
1524
+
1525
+ if (videoWidth > playerWidth) {
1526
+ this.execute('setSize', '100%', 'auto');
1527
+ } else {
1528
+ this.$component.css({
1529
+ maxHeight: "".concat(this.config.height + controlsHeight, "px")
1530
+ });
1531
+ this.execute('setSize', Math.floor(videoWidth), 'auto');
1532
+ }
1533
+ },
1534
+
1535
+ /**
1536
+ * Update volume in DBIndex store
1537
+ * @param {Number} volume
1538
+ * @returns {Promise}
1539
+ * @private
1540
+ */
1541
+ _storeVolume: function _storeVolume(volume) {
1542
+ return store('mediaVolume').then(function (volumeStore) {
1543
+ return volumeStore.setItem('volume', volume);
1544
+ });
1545
+ },
1591
1546
 
1547
+ /**
1548
+ * Get volume from DBIndex store
1549
+ * @returns {Promise}
1550
+ * @private
1551
+ */
1552
+ _updateVolumeFromStore: function _updateVolumeFromStore() {
1553
+ var _this8 = this;
1592
1554
 
1593
- this.trigger('limitreached');
1594
- } else if (this.loop) {
1595
- this.restart();
1596
- } else if (parseInt(this.config.replayTimeout, 10) > 0) {
1597
- this.replayTimeoutStartMs = new window.Date().getTime();
1555
+ return store('mediaVolume').then(function (volumeStore) {
1556
+ return volumeStore.getItem('volume');
1557
+ }).then(function (volume) {
1558
+ if (_.isNumber(volume)) {
1559
+ _this8.volume = Math.max(volumeMin, Math.min(volumeMax, parseFloat(volume)));
1598
1560
 
1599
- this._replayTimeout();
1561
+ _this8.setVolume(_this8.volume);
1600
1562
  }
1601
- /**
1602
- * Triggers a media ended event
1603
- * @event mediaplayer#ended
1604
- */
1605
-
1563
+ });
1564
+ },
1606
1565
 
1607
- this.trigger('ended');
1608
- },
1566
+ /**
1567
+ * Event called when the media throws unrecoverable error
1568
+ * @private
1569
+ */
1570
+ _onError: function _onError() {
1571
+ this._setState('error', true);
1609
1572
 
1573
+ this._setState('loading', false);
1610
1574
  /**
1611
- * Event called when the playback is playing
1612
- * @private
1575
+ * Triggers an unrecoverable media error event
1576
+ * @event mediaplayer#error
1613
1577
  */
1614
- _onPlaying() {
1615
- this._setState('preview', true);
1616
1578
 
1617
- this._setState('stalled', false);
1618
1579
 
1619
- this._setState('ready', true);
1620
- },
1580
+ this.trigger('error');
1581
+ },
1582
+
1583
+ /**
1584
+ * Event called when the media is played
1585
+ * @private
1586
+ */
1587
+ _onPlay: function _onPlay() {
1588
+ this._playingState(true);
1621
1589
 
1590
+ this._setState('preview', true);
1622
1591
  /**
1623
- * Event called when the playback is stalled
1624
- * @private
1592
+ * Triggers a media playback event
1593
+ * @event mediaplayer#play
1625
1594
  */
1626
- _onStalled() {
1627
- this._setState('stalled', true);
1628
1595
 
1629
- this._setState('ready', false);
1630
- },
1631
1596
 
1597
+ this.trigger('play', this.player && this.player.getMedia());
1598
+ },
1599
+
1600
+ /**
1601
+ * Event called when the media is paused
1602
+ * @private
1603
+ */
1604
+ _onPause: function _onPause() {
1605
+ this._playingState(false);
1632
1606
  /**
1633
- * Event called when the time position has changed
1634
- * @private
1607
+ * Triggers a media paused event
1608
+ * @event mediaplayer#pause
1635
1609
  */
1636
- _onTimeUpdate() {
1637
- this._updatePosition(this.player.getPosition());
1638
- /**
1639
- * Triggers a media time update event
1640
- * @event mediaplayer#update
1641
- */
1642
1610
 
1643
1611
 
1644
- this.trigger('update');
1645
- },
1612
+ this.trigger('pause');
1613
+ },
1646
1614
 
1647
- /**
1648
- * Run a timer to disable the possibility of replaying a media
1649
- * @private
1650
- */
1651
- _replayTimeout() {
1652
- const nowMs = new window.Date().getTime(),
1653
- elapsedSeconds = Math.floor((nowMs - this.replayTimeoutStartMs) / 1000);
1654
- this.timerId = requestAnimationFrame(this._replayTimeout.bind(this));
1615
+ /**
1616
+ * Event called when the media is ended
1617
+ * @private
1618
+ */
1619
+ _onEnd: function _onEnd() {
1620
+ this.timesPlayed++;
1621
+
1622
+ this._playingState(false, true);
1623
+
1624
+ this._updatePosition(0); // disable when the play limit is reached
1655
1625
 
1656
- if (elapsedSeconds >= parseInt(this.config.replayTimeout, 10)) {
1626
+
1627
+ if (this._playLimitReached()) {
1628
+ if (!this.is('disabled')) {
1657
1629
  this.disable();
1658
- cancelAnimationFrame(this.timerId);
1659
1630
  }
1660
- },
1631
+ /**
1632
+ * Triggers a play limit reached event
1633
+ * @event mediaplayer#limitreached
1634
+ */
1661
1635
 
1662
- /**
1663
- * Checks if the play limit has been reached
1664
- * @returns {Boolean}
1665
- * @private
1666
- */
1667
- _playLimitReached() {
1668
- return this.config.maxPlays && this.timesPlayed >= this.config.maxPlays;
1669
- },
1670
1636
 
1671
- /**
1672
- * Checks if the media can be played
1673
- * @returns {Boolean}
1674
- * @private
1675
- */
1676
- _canPlay() {
1677
- return (this.is('ready') || this.is('stalled')) && !this.is('disabled') && !this.is('hidden') && !this._playLimitReached();
1678
- },
1637
+ this.trigger('limitreached');
1638
+ } else if (this.loop) {
1639
+ this.restart();
1640
+ } else if (parseInt(this.config.replayTimeout, 10) > 0) {
1641
+ this.replayTimeoutStartMs = new window.Date().getTime();
1679
1642
 
1643
+ this._replayTimeout();
1644
+ }
1680
1645
  /**
1681
- * Checks if the media can be paused
1682
- * @returns {Boolean}
1683
- * @private
1646
+ * Triggers a media ended event
1647
+ * @event mediaplayer#ended
1684
1648
  */
1685
- _canPause() {
1686
- return !!this.config.canPause;
1687
- },
1688
1649
 
1689
- /**
1690
- * Checks if the media can be sought
1691
- * @returns {Boolean}
1692
- * @private
1693
- */
1694
- _canSeek() {
1695
- return !!this.config.canSeek;
1696
- },
1697
1650
 
1698
- /**
1699
- * Checks if the playback can be resumed
1700
- * @returns {Boolean}
1701
- * @private
1702
- */
1703
- _canResume() {
1704
- return this.is('paused') && this._canPlay();
1705
- },
1651
+ this.trigger('ended');
1652
+ },
1706
1653
 
1707
- /**
1708
- * Sets the media is in a particular state
1709
- * @param {String} name
1710
- * @param {Boolean} value
1711
- * @returns {mediaplayer}
1712
- */
1713
- _setState(name, value) {
1714
- value = !!value;
1715
- this.config.is[name] = value;
1654
+ /**
1655
+ * Event called when the playback is playing
1656
+ * @private
1657
+ */
1658
+ _onPlaying: function _onPlaying() {
1659
+ this._setState('preview', true);
1716
1660
 
1717
- if (this.$component) {
1718
- this.$component.toggleClass(name, value);
1719
- }
1661
+ this._setState('stalled', false);
1720
1662
 
1721
- return this;
1722
- },
1663
+ this._setState('ready', true);
1664
+ },
1723
1665
 
1724
- /**
1725
- * Restores the media player from a particular state and resumes the playback
1726
- * @param {String} stateName
1727
- * @returns {mediaplayer}
1728
- * @private
1729
- */
1730
- _fromState(stateName) {
1731
- this._setState(stateName, false);
1666
+ /**
1667
+ * Event called when the playback is stalled
1668
+ * @private
1669
+ */
1670
+ _onStalled: function _onStalled() {
1671
+ this._setState('stalled', true);
1732
1672
 
1733
- this.resume();
1734
- return this;
1735
- },
1673
+ this._setState('ready', false);
1674
+ },
1736
1675
 
1676
+ /**
1677
+ * Event called when the time position has changed
1678
+ * @private
1679
+ */
1680
+ _onTimeUpdate: function _onTimeUpdate() {
1681
+ this._updatePosition(this.player.getPosition());
1737
1682
  /**
1738
- * Sets the media player to a particular state and pauses the playback
1739
- * @param {String} stateName
1740
- * @returns {mediaplayer}
1741
- * @private
1683
+ * Triggers a media time update event
1684
+ * @event mediaplayer#update
1742
1685
  */
1743
- _toState(stateName) {
1744
- this.pause();
1745
1686
 
1746
- this._setState(stateName, true);
1747
1687
 
1748
- return this;
1749
- },
1688
+ this.trigger('update');
1689
+ },
1750
1690
 
1751
- /**
1752
- * Sets the playing state
1753
- * @param {Boolean} state
1754
- * @param {Boolean} [ended]
1755
- * @returns {mediaplayer}
1756
- * @private
1757
- */
1758
- _playingState(state, ended) {
1759
- this._setState('playing', !!state);
1691
+ /**
1692
+ * Run a timer to disable the possibility of replaying a media
1693
+ * @private
1694
+ */
1695
+ _replayTimeout: function _replayTimeout() {
1696
+ var nowMs = new window.Date().getTime(),
1697
+ elapsedSeconds = Math.floor((nowMs - this.replayTimeoutStartMs) / 1000);
1698
+ this.timerId = requestAnimationFrame(this._replayTimeout.bind(this));
1699
+
1700
+ if (elapsedSeconds >= parseInt(this.config.replayTimeout, 10)) {
1701
+ this.disable();
1702
+ cancelAnimationFrame(this.timerId);
1703
+ }
1704
+ },
1760
1705
 
1761
- this._setState('paused', !state);
1706
+ /**
1707
+ * Checks if the play limit has been reached
1708
+ * @returns {Boolean}
1709
+ * @private
1710
+ */
1711
+ _playLimitReached: function _playLimitReached() {
1712
+ return this.config.maxPlays && this.timesPlayed >= this.config.maxPlays;
1713
+ },
1762
1714
 
1763
- this._setState('ended', !!ended);
1715
+ /**
1716
+ * Checks if the media can be played
1717
+ * @returns {Boolean}
1718
+ * @private
1719
+ */
1720
+ _canPlay: function _canPlay() {
1721
+ return (this.is('ready') || this.is('stalled')) && !this.is('disabled') && !this.is('hidden') && !this._playLimitReached();
1722
+ },
1764
1723
 
1765
- return this;
1766
- },
1724
+ /**
1725
+ * Checks if the media can be paused
1726
+ * @returns {Boolean}
1727
+ * @private
1728
+ */
1729
+ _canPause: function _canPause() {
1730
+ return !!this.config.canPause;
1731
+ },
1767
1732
 
1768
- /**
1769
- * Executes a command onto the media
1770
- * @param {String} command - The name of the command to execute
1771
- * @param {*} args - additional arguments
1772
- * @returns {*}
1773
- * @private
1774
- */
1775
- execute(command) {
1776
- if (this.player && 'function' === typeof this.player[command]) {
1777
- for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1778
- args[_key2 - 1] = arguments[_key2];
1779
- }
1733
+ /**
1734
+ * Checks if the media can be sought
1735
+ * @returns {Boolean}
1736
+ * @private
1737
+ */
1738
+ _canSeek: function _canSeek() {
1739
+ return !!this.config.canSeek;
1740
+ },
1780
1741
 
1781
- return this.player[command](...args);
1782
- }
1742
+ /**
1743
+ * Checks if the playback can be resumed
1744
+ * @returns {Boolean}
1745
+ * @private
1746
+ */
1747
+ _canResume: function _canResume() {
1748
+ return this.is('paused') && this._canPlay();
1749
+ },
1750
+
1751
+ /**
1752
+ * Sets the media is in a particular state
1753
+ * @param {String} name
1754
+ * @param {Boolean} value
1755
+ * @returns {mediaplayer}
1756
+ */
1757
+ _setState: function _setState(name, value) {
1758
+ value = !!value;
1759
+ this.config.is[name] = value;
1760
+
1761
+ if (this.$component) {
1762
+ this.$component.toggleClass(name, value);
1783
1763
  }
1784
1764
 
1785
- };
1786
- return mediaplayer.init(config);
1787
- }
1788
- /**
1789
- * Tells if the browser can play audio and video
1790
- * @param {String} [type] The type of media (audio or video)
1791
- * @param {String} [mime] A media MIME type to check
1792
- * @type {Boolean}
1793
- */
1765
+ return this;
1766
+ },
1794
1767
 
1768
+ /**
1769
+ * Restores the media player from a particular state and resumes the playback
1770
+ * @param {String} stateName
1771
+ * @returns {mediaplayer}
1772
+ * @private
1773
+ */
1774
+ _fromState: function _fromState(stateName) {
1775
+ this._setState(stateName, false);
1795
1776
 
1796
- mediaplayerFactory.canPlay = function canPlay(type, mime) {
1797
- return support.canPlay(type, mime);
1798
- };
1799
- /**
1800
- * Tells if the browser can play audio
1801
- * @param {String} [mime] A media MIME type to check
1802
- * @type {Boolean}
1803
- */
1777
+ this.resume();
1778
+ return this;
1779
+ },
1804
1780
 
1781
+ /**
1782
+ * Sets the media player to a particular state and pauses the playback
1783
+ * @param {String} stateName
1784
+ * @returns {mediaplayer}
1785
+ * @private
1786
+ */
1787
+ _toState: function _toState(stateName) {
1788
+ this.pause();
1805
1789
 
1806
- mediaplayerFactory.canPlayAudio = function canPlayAudio(mime) {
1807
- return support.canPlayAudio(mime);
1808
- };
1809
- /**
1810
- * Tells if the browser can play video
1811
- * @param {String} [mime] A media MIME type to check
1812
- * @type {Boolean}
1813
- */
1790
+ this._setState(stateName, true);
1814
1791
 
1792
+ return this;
1793
+ },
1815
1794
 
1816
- mediaplayerFactory.canPlayVideo = function canPlayVideo(mime) {
1817
- return support.canPlayVideo(mime);
1818
- };
1819
- /**
1820
- * Checks if the browser allows to control the media playback
1821
- * @returns {Boolean}
1822
- */
1795
+ /**
1796
+ * Sets the playing state
1797
+ * @param {Boolean} state
1798
+ * @param {Boolean} [ended]
1799
+ * @returns {mediaplayer}
1800
+ * @private
1801
+ */
1802
+ _playingState: function _playingState(state, ended) {
1803
+ this._setState('playing', !!state);
1823
1804
 
1805
+ this._setState('paused', !state);
1824
1806
 
1825
- mediaplayerFactory.canControl = function canControl() {
1826
- return support.canControl();
1827
- };
1807
+ this._setState('ended', !!ended);
1808
+
1809
+ return this;
1810
+ },
1828
1811
 
1829
- return mediaplayerFactory;
1812
+ /**
1813
+ * Executes a command onto the media
1814
+ * @param {String} command - The name of the command to execute
1815
+ * @param {*} args - additional arguments
1816
+ * @returns {*}
1817
+ * @private
1818
+ */
1819
+ execute: function execute(command) {
1820
+ if (this.player && 'function' === typeof this.player[command]) {
1821
+ var _this$player;
1822
+
1823
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
1824
+ args[_key2 - 1] = arguments[_key2];
1825
+ }
1826
+
1827
+ return (_this$player = this.player)[command].apply(_this$player, args);
1828
+ }
1829
+ }
1830
+ };
1831
+ return mediaplayer.init(config);
1832
+ }
1833
+ /**
1834
+ * Tells if the browser can play audio and video
1835
+ * @param {String} [type] The type of media (audio or video)
1836
+ * @param {String} [mime] A media MIME type to check
1837
+ * @type {Boolean}
1838
+ */
1839
+
1840
+
1841
+ mediaplayerFactory.canPlay = function canPlay(type, mime) {
1842
+ return support.canPlay(type, mime);
1843
+ };
1844
+ /**
1845
+ * Tells if the browser can play audio
1846
+ * @param {String} [mime] A media MIME type to check
1847
+ * @type {Boolean}
1848
+ */
1849
+
1850
+
1851
+ mediaplayerFactory.canPlayAudio = function canPlayAudio(mime) {
1852
+ return support.canPlayAudio(mime);
1853
+ };
1854
+ /**
1855
+ * Tells if the browser can play video
1856
+ * @param {String} [mime] A media MIME type to check
1857
+ * @type {Boolean}
1858
+ */
1859
+
1860
+
1861
+ mediaplayerFactory.canPlayVideo = function canPlayVideo(mime) {
1862
+ return support.canPlayVideo(mime);
1863
+ };
1864
+ /**
1865
+ * Checks if the browser allows to control the media playback
1866
+ * @returns {Boolean}
1867
+ */
1868
+
1869
+
1870
+ mediaplayerFactory.canControl = function canControl() {
1871
+ return support.canControl();
1872
+ };
1873
+
1874
+ return mediaplayerFactory;
1830
1875
 
1831
1876
  });