Version 1
[yaffs-website] / node_modules / video.js / es5 / modal-dialog.js
1 'use strict';
2
3 exports.__esModule = true;
4
5 var _dom = require('./utils/dom');
6
7 var Dom = _interopRequireWildcard(_dom);
8
9 var _fn = require('./utils/fn');
10
11 var Fn = _interopRequireWildcard(_fn);
12
13 var _component = require('./component');
14
15 var _component2 = _interopRequireDefault(_component);
16
17 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18
19 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
20
21 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22
23 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
24
25 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
26                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 * @file modal-dialog.js
27                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 */
28
29
30 var MODAL_CLASS_NAME = 'vjs-modal-dialog';
31 var ESC = 27;
32
33 /**
34  * The `ModalDialog` displays over the video and its controls, which blocks
35  * interaction with the player until it is closed.
36  *
37  * Modal dialogs include a "Close" button and will close when that button
38  * is activated - or when ESC is pressed anywhere.
39  *
40  * @extends Component
41  */
42
43 var ModalDialog = function (_Component) {
44   _inherits(ModalDialog, _Component);
45
46   /**
47    * Create an instance of this class.
48    *
49    * @param {Player} player
50    *        The `Player` that this class should be attached to.
51    *
52    * @param {Object} [options]
53    *        The key/value store of player options.
54    *
55    * @param {Mixed} [options.content=undefined]
56    *        Provide customized content for this modal.
57    *
58    * @param {string} [options.description]
59    *        A text description for the modal, primarily for accessibility.
60    *
61    * @param {boolean} [options.fillAlways=false]
62    *        Normally, modals are automatically filled only the first time
63    *        they open. This tells the modal to refresh its content
64    *        every time it opens.
65    *
66    * @param {string} [options.label]
67    *        A text label for the modal, primarily for accessibility.
68    *
69    * @param {boolean} [options.temporary=true]
70    *        If `true`, the modal can only be opened once; it will be
71    *        disposed as soon as it's closed.
72    *
73    * @param {boolean} [options.uncloseable=false]
74    *        If `true`, the user will not be able to close the modal
75    *        through the UI in the normal ways. Programmatic closing is
76    *        still possible.
77    */
78   function ModalDialog(player, options) {
79     _classCallCheck(this, ModalDialog);
80
81     var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
82
83     _this.opened_ = _this.hasBeenOpened_ = _this.hasBeenFilled_ = false;
84
85     _this.closeable(!_this.options_.uncloseable);
86     _this.content(_this.options_.content);
87
88     // Make sure the contentEl is defined AFTER any children are initialized
89     // because we only want the contents of the modal in the contentEl
90     // (not the UI elements like the close button).
91     _this.contentEl_ = Dom.createEl('div', {
92       className: MODAL_CLASS_NAME + '-content'
93     }, {
94       role: 'document'
95     });
96
97     _this.descEl_ = Dom.createEl('p', {
98       className: MODAL_CLASS_NAME + '-description vjs-offscreen',
99       id: _this.el().getAttribute('aria-describedby')
100     });
101
102     Dom.textContent(_this.descEl_, _this.description());
103     _this.el_.appendChild(_this.descEl_);
104     _this.el_.appendChild(_this.contentEl_);
105     return _this;
106   }
107
108   /**
109    * Create the `ModalDialog`'s DOM element
110    *
111    * @return {Element}
112    *         The DOM element that gets created.
113    */
114
115
116   ModalDialog.prototype.createEl = function createEl() {
117     return _Component.prototype.createEl.call(this, 'div', {
118       className: this.buildCSSClass(),
119       tabIndex: -1
120     }, {
121       'aria-describedby': this.id() + '_description',
122       'aria-hidden': 'true',
123       'aria-label': this.label(),
124       'role': 'dialog'
125     });
126   };
127
128   /**
129    * Builds the default DOM `className`.
130    *
131    * @return {string}
132    *         The DOM `className` for this object.
133    */
134
135
136   ModalDialog.prototype.buildCSSClass = function buildCSSClass() {
137     return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this);
138   };
139
140   /**
141    * Handles `keydown` events on the document, looking for ESC, which closes
142    * the modal.
143    *
144    * @param {EventTarget~Event} e
145    *        The keypress that triggered this event.
146    *
147    * @listens keydown
148    */
149
150
151   ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) {
152     if (e.which === ESC && this.closeable()) {
153       this.close();
154     }
155   };
156
157   /**
158    * Returns the label string for this modal. Primarily used for accessibility.
159    *
160    * @return {string}
161    *         the localized or raw label of this modal.
162    */
163
164
165   ModalDialog.prototype.label = function label() {
166     return this.options_.label || this.localize('Modal Window');
167   };
168
169   /**
170    * Returns the description string for this modal. Primarily used for
171    * accessibility.
172    *
173    * @return {string}
174    *         The localized or raw description of this modal.
175    */
176
177
178   ModalDialog.prototype.description = function description() {
179     var desc = this.options_.description || this.localize('This is a modal window.');
180
181     // Append a universal closeability message if the modal is closeable.
182     if (this.closeable()) {
183       desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.');
184     }
185
186     return desc;
187   };
188
189   /**
190    * Opens the modal.
191    *
192    * @fires ModalDialog#beforemodalopen
193    * @fires ModalDialog#modalopen
194    *
195    * @return {ModalDialog}
196    *         Returns itself; method can be chained.
197    */
198
199
200   ModalDialog.prototype.open = function open() {
201     if (!this.opened_) {
202       var player = this.player();
203
204       /**
205        * Fired just before a `ModalDialog` is opened.
206        *
207        * @event ModalDialog#beforemodalopen
208        * @type {EventTarget~Event}
209        */
210       this.trigger('beforemodalopen');
211       this.opened_ = true;
212
213       // Fill content if the modal has never opened before and
214       // never been filled.
215       if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) {
216         this.fill();
217       }
218
219       // If the player was playing, pause it and take note of its previously
220       // playing state.
221       this.wasPlaying_ = !player.paused();
222
223       if (this.options_.pauseOnOpen && this.wasPlaying_) {
224         player.pause();
225       }
226
227       if (this.closeable()) {
228         this.on(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
229       }
230
231       player.controls(false);
232       this.show();
233       this.el().setAttribute('aria-hidden', 'false');
234
235       /**
236        * Fired just after a `ModalDialog` is opened.
237        *
238        * @event ModalDialog#modalopen
239        * @type {EventTarget~Event}
240        */
241       this.trigger('modalopen');
242       this.hasBeenOpened_ = true;
243     }
244     return this;
245   };
246
247   /**
248    * If the `ModalDialog` is currently open or closed.
249    *
250    * @param  {boolean} [value]
251    *         If given, it will open (`true`) or close (`false`) the modal.
252    *
253    * @return {boolean}
254    *         the current open state of the modaldialog
255    */
256
257
258   ModalDialog.prototype.opened = function opened(value) {
259     if (typeof value === 'boolean') {
260       this[value ? 'open' : 'close']();
261     }
262     return this.opened_;
263   };
264
265   /**
266    * Closes the modal, does nothing if the `ModalDialog` is
267    * not open.
268    *
269    * @fires ModalDialog#beforemodalclose
270    * @fires ModalDialog#modalclose
271    *
272    * @return {ModalDialog}
273    *         Returns itself; method can be chained.
274    */
275
276
277   ModalDialog.prototype.close = function close() {
278     if (this.opened_) {
279       var player = this.player();
280
281       /**
282        * Fired just before a `ModalDialog` is closed.
283        *
284        * @event ModalDialog#beforemodalclose
285        * @type {EventTarget~Event}
286        */
287       this.trigger('beforemodalclose');
288       this.opened_ = false;
289
290       if (this.wasPlaying_ && this.options_.pauseOnOpen) {
291         player.play();
292       }
293
294       if (this.closeable()) {
295         this.off(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
296       }
297
298       player.controls(true);
299       this.hide();
300       this.el().setAttribute('aria-hidden', 'true');
301
302       /**
303        * Fired just after a `ModalDialog` is closed.
304        *
305        * @event ModalDialog#modalclose
306        * @type {EventTarget~Event}
307        */
308       this.trigger('modalclose');
309
310       if (this.options_.temporary) {
311         this.dispose();
312       }
313     }
314     return this;
315   };
316
317   /**
318    * Check to see if the `ModalDialog` is closeable via the UI.
319    *
320    * @param  {boolean} [value]
321    *         If given as a boolean, it will set the `closeable` option.
322    *
323    * @return {boolean}
324    *         Returns the final value of the closable option.
325    */
326
327
328   ModalDialog.prototype.closeable = function closeable(value) {
329     if (typeof value === 'boolean') {
330       var closeable = this.closeable_ = !!value;
331       var close = this.getChild('closeButton');
332
333       // If this is being made closeable and has no close button, add one.
334       if (closeable && !close) {
335
336         // The close button should be a child of the modal - not its
337         // content element, so temporarily change the content element.
338         var temp = this.contentEl_;
339
340         this.contentEl_ = this.el_;
341         close = this.addChild('closeButton', { controlText: 'Close Modal Dialog' });
342         this.contentEl_ = temp;
343         this.on(close, 'close', this.close);
344       }
345
346       // If this is being made uncloseable and has a close button, remove it.
347       if (!closeable && close) {
348         this.off(close, 'close', this.close);
349         this.removeChild(close);
350         close.dispose();
351       }
352     }
353     return this.closeable_;
354   };
355
356   /**
357    * Fill the modal's content element with the modal's "content" option.
358    * The content element will be emptied before this change takes place.
359    *
360    * @return {ModalDialog}
361    *         Returns itself; method can be chained.
362    */
363
364
365   ModalDialog.prototype.fill = function fill() {
366     return this.fillWith(this.content());
367   };
368
369   /**
370    * Fill the modal's content element with arbitrary content.
371    * The content element will be emptied before this change takes place.
372    *
373    * @fires ModalDialog#beforemodalfill
374    * @fires ModalDialog#modalfill
375    *
376    * @param  {Mixed} [content]
377    *         The same rules apply to this as apply to the `content` option.
378    *
379    * @return {ModalDialog}
380    *         Returns itself; method can be chained.
381    */
382
383
384   ModalDialog.prototype.fillWith = function fillWith(content) {
385     var contentEl = this.contentEl();
386     var parentEl = contentEl.parentNode;
387     var nextSiblingEl = contentEl.nextSibling;
388
389     /**
390      * Fired just before a `ModalDialog` is filled with content.
391      *
392      * @event ModalDialog#beforemodalfill
393      * @type {EventTarget~Event}
394      */
395     this.trigger('beforemodalfill');
396     this.hasBeenFilled_ = true;
397
398     // Detach the content element from the DOM before performing
399     // manipulation to avoid modifying the live DOM multiple times.
400     parentEl.removeChild(contentEl);
401     this.empty();
402     Dom.insertContent(contentEl, content);
403     /**
404      * Fired just after a `ModalDialog` is filled with content.
405      *
406      * @event ModalDialog#modalfill
407      * @type {EventTarget~Event}
408      */
409     this.trigger('modalfill');
410
411     // Re-inject the re-filled content element.
412     if (nextSiblingEl) {
413       parentEl.insertBefore(contentEl, nextSiblingEl);
414     } else {
415       parentEl.appendChild(contentEl);
416     }
417
418     return this;
419   };
420
421   /**
422    * Empties the content element. This happens anytime the modal is filled.
423    *
424    * @fires ModalDialog#beforemodalempty
425    * @fires ModalDialog#modalempty
426    *
427    * @return {ModalDialog}
428    *         Returns itself; method can be chained.
429    */
430
431
432   ModalDialog.prototype.empty = function empty() {
433     /**
434      * Fired just before a `ModalDialog` is emptied.
435      *
436      * @event ModalDialog#beforemodalempty
437      * @type {EventTarget~Event}
438      */
439     this.trigger('beforemodalempty');
440     Dom.emptyEl(this.contentEl());
441
442     /**
443      * Fired just after a `ModalDialog` is emptied.
444      *
445      * @event ModalDialog#modalempty
446      * @type {EventTarget~Event}
447      */
448     this.trigger('modalempty');
449     return this;
450   };
451
452   /**
453    * Gets or sets the modal content, which gets normalized before being
454    * rendered into the DOM.
455    *
456    * This does not update the DOM or fill the modal, but it is called during
457    * that process.
458    *
459    * @param  {Mixed} [value]
460    *         If defined, sets the internal content value to be used on the
461    *         next call(s) to `fill`. This value is normalized before being
462    *         inserted. To "clear" the internal content value, pass `null`.
463    *
464    * @return {Mixed}
465    *         The current content of the modal dialog
466    */
467
468
469   ModalDialog.prototype.content = function content(value) {
470     if (typeof value !== 'undefined') {
471       this.content_ = value;
472     }
473     return this.content_;
474   };
475
476   return ModalDialog;
477 }(_component2['default']);
478
479 /**
480  * Default options for `ModalDialog` default options.
481  *
482  * @type {Object}
483  * @private
484  */
485
486
487 ModalDialog.prototype.options_ = {
488   pauseOnOpen: true,
489   temporary: true
490 };
491
492 _component2['default'].registerComponent('ModalDialog', ModalDialog);
493 exports['default'] = ModalDialog;