/** * Provides a simple Container for HTML5 Video. * * ## Notes * * - There are quite a few issues with the `<video>` tag on Android devices. On Android 2+, the video will * appear and play on first attempt, but any attempt afterwards will not work. * * ## Useful Properties * * - {@link #url} * - {@link #autoPause} * - {@link #autoResume} * * ## Useful Methods * * - {@link #method-pause} * - {@link #method-play} * - {@link #toggle} * * ## Example * * var panel = Ext.create('Ext.Panel', { * fullscreen: true, * items: [ * { * xtype : 'video', * x : 600, * y : 300, * width : 175, * height : 98, * url : "porsche911.mov", * posterUrl: 'porsche.png' * } * ] * }); */Ext.define('Ext.Video', { extend: 'Ext.Media', xtype: 'video', config: { /** * @cfg {String/Array} url * Location of the video to play. This should be in H.264 format and in a .mov file format. * @accessor */ /** * @cfg {String} posterUrl * Location of a poster image to be shown before showing the video. * @accessor */ posterUrl: null, /** * @cfg * @inheritdoc */ baseCls: Ext.baseCSSPrefix + 'video', /** * @cfg {Boolean} controls * Determines if native controls should be shown for this video player. */ controls: true }, template: [{ /** * @property {Ext.dom.Element} ghost * @private */ reference: 'ghost', classList: [Ext.baseCSSPrefix + 'video-ghost'] }, { tag: 'video', reference: 'media', classList: [Ext.baseCSSPrefix + 'media'] }], initialize: function() { var me = this; me.callParent(); me.media.hide(); me.ghost.on({ tap: 'onGhostTap', scope: me }); me.media.on({ pause: 'onPause', scope: me }); if (Ext.os.is.Android4 || Ext.os.is.iPad) { this.isInlineVideo = true; } }, applyUrl: function(url) { return [].concat(url); }, updateUrl: function(newUrl) { var me = this, media = me.media, newLn = newUrl.length, existingSources = media.query('source'), oldLn = existingSources.length, i; for (i = 0; i < oldLn; i++) { Ext.fly(existingSources[i]).destroy(); } for (i = 0; i < newLn; i++) { media.appendChild(Ext.Element.create({ tag: 'source', src: newUrl[i] })); } if (me.isPlaying()) { me.play(); } }, updateControls: function(value) { this.media.set({controls:value ? true : undefined}); }, onActivate: function() { this.media.setTop(0); }, onDeactivate: function() { this.pause(); this.media.setTop(-2000); this.ghost.show(); }, /** * @private * Called when the {@link #ghost} element is tapped. */ onGhostTap: function() { var me = this, media = this.media, ghost = this.ghost; media.show(); // Browsers which support native video tag display only, move the media down so // we can control the Viewport ghost.hide(); me.play(); }, /** * @private * native video tag display only, move the media down so we can control the Viewport */ onPause: function() { this.callParent(arguments); if (!this.isInlineVideo) { this.media.setTop(-2000); this.ghost.show(); } }, /** * @private * native video tag display only, move the media down so we can control the Viewport */ onPlay: function() { this.callParent(arguments); this.media.setTop(0); }, /** * Updates the URL to the poster, even if it is rendered. * @param {Object} newUrl */ updatePosterUrl: function(newUrl) { var ghost = this.ghost; if (ghost) { ghost.setStyle('background-image', 'url(' + newUrl + ')'); } }});